home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / comm / bytecomm.zip / COMM.C < prev    next >
C/C++ Source or Header  |  1991-07-25  |  195KB  |  6,783 lines

  1.  
  2. /*      COMM.C                                      */
  3.  
  4. /*      background communications program           */ 
  5. /*      Copyright (c) 1989, 1991 Barry R. Nance     */
  6.  
  7. #pragma  inline
  8. #include <stdio.h>
  9. #include <dos.h>
  10. #include <dir.h>
  11. #include <mem.h>
  12. #include <io.h>
  13. #include <conio.h>
  14. #include <bios.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <stddef.h>
  18. #include <stdarg.h>
  19. #include <ctype.h>
  20. #include "comm.h"
  21.  
  22. /* ------------------------------------------- */
  23.  
  24. char        compliments[] = "BYTE Magazine--Software Corner Telecomm Pgm";
  25.  
  26. unsigned    paragraphs;
  27. unsigned    temp1, temp2;
  28. char        crit_err_occurred = FALSE;
  29. char        critical_error = FALSE;
  30. int         i, j, k;
  31. int         c  = 0;
  32. int         xc = 0;
  33. char        ch = 0;
  34.  
  35. struct date   today;
  36.  
  37. unsigned      old_ss, old_sp, our_ss, our_sp;
  38. unsigned char kbd_code;
  39. unsigned char prev_kbd_code;
  40. unsigned char alt_menu = FALSE;
  41. unsigned char use_alt  = TRUE;
  42. unsigned char function_id;
  43. long     far  *sk_ptr1;
  44. unsigned far  *sk_ptr2;
  45.  
  46. char        far *ourdta_ptr;
  47. char        far *olddta_ptr;
  48.  
  49. char        far *our_mcb;
  50. unsigned    far *our_mcb_size;
  51. char        far *next_mcb;
  52. unsigned    far *next_mcb_owner;
  53. unsigned    ourpsp;
  54. unsigned    oldpsp;
  55. int         break_state;
  56.  
  57. void     interrupt (*oldint08)(void);
  58. void     interrupt (*oldint09)(void);
  59. void     interrupt (*oldint10)(void);
  60. void     interrupt (*oldint13)(void);
  61. void     interrupt (*oldint16)(void);
  62. void     interrupt (*oldint1b)(void);
  63. void     interrupt (*oldint1c)(void);
  64. void     interrupt (*oldint21)(void);
  65. void     interrupt (*oldint23)(void);
  66. void     interrupt (*oldint24)(void);
  67. void     interrupt (*oldint28)(void);
  68. void     interrupt (*oldint0b)(void);
  69. void     interrupt (*oldint0c)(void);
  70. void     interrupt (*vectsave)(void);
  71. void     interrupt (*vecthold)(void);
  72.  
  73. char far             *kbd_flag_ptr;
  74. unsigned char far    *prtsc_flag_ptr;
  75. unsigned char far    *indos_ptr;
  76. unsigned char far    *indos2_ptr;
  77.  
  78. volatile unsigned char    in_int08 = FALSE;
  79. volatile unsigned char    in_int09 = FALSE;
  80. volatile unsigned char    in_int10 = FALSE;
  81. volatile unsigned char    in_int13 = FALSE;
  82. volatile unsigned char    in_int16 = FALSE;
  83. volatile unsigned char    in_int21 = FALSE;
  84. volatile unsigned char    in_int28 = FALSE;
  85. volatile unsigned char    in_popup = FALSE;
  86. volatile unsigned char    in_background = FALSE;
  87. volatile unsigned char    pass_through   = FALSE;
  88. volatile unsigned char    hot_flag = FALSE;
  89. volatile unsigned char    leave_flag = FALSE;
  90. volatile unsigned char    de_install = FALSE;
  91.  
  92. unsigned char    first_time = TRUE;
  93. unsigned char    first_menu_appearance = TRUE;
  94. unsigned char    call_in_progress= FALSE;
  95. unsigned char    use_carrier = TRUE;
  96.  
  97. volatile long    tick_counter  = 0l;
  98. volatile long    next_fg_slice = 0l;
  99. volatile long    next_bg_slice = 0l;
  100. volatile long    timeout_ticks = 0l;
  101. volatile long    timeout_value = 0l;
  102. volatile long    commit_ticks  = 0l;
  103.  
  104. unsigned int     xtimeout  = 2;
  105. long             xticks    = 0;
  106. unsigned int     foreground_ticks = 8;
  107. unsigned int     background_ticks = 3;
  108. unsigned int     dial_wait_secs   = 30;
  109. unsigned int     break_milliseconds = 250;
  110. int              handle    = 0;
  111. int              io_len    = 0;
  112. unsigned int     fbufndx   = 2000;
  113. unsigned int     fbufbytes = 0;
  114.  
  115. int              config_error = 0;
  116. int              dial_error   = 0;
  117.  
  118. char             *config_msg[18] = {
  119.                     "file not found",
  120.                     "reg. fg. color",
  121.                     "reg. bg. color",
  122.                     "msg. fg. color",
  123.                     "msg. bg. color",
  124.                     "comm. port #",
  125.                     "baud rate",
  126.                     "data bits",
  127.                     "parity",
  128.                     "stop bits",
  129.                     "echo toggle",
  130.                     "break ticks",
  131.                     "foreg ticks",
  132.                     "backg ticks",
  133.                     "dial wait",
  134.                     "init menu",
  135.                     "xmodem timeout",
  136.                     "macro def."
  137.                     };
  138.  
  139.  
  140. char             *dial_msg[10] =   {
  141.                     "parms",
  142.                     "name",
  143.                     "number",
  144.                     "baudrate",
  145.                     "data bits",
  146.                     "parity",
  147.                     "stop bits",
  148.                     "echo flag",
  149.                     "flow ctrl",
  150.                     "add lf"
  151.                     };
  152.  
  153. char             string1[LINE_LENGTH];
  154. char             string2[LINE_LENGTH];
  155. char             string3[LINE_LENGTH];
  156. char             holdstr[LINE_LENGTH];
  157.  
  158. char             kbd_macro1[LINE_LENGTH];
  159. char             kbd_macro2[LINE_LENGTH];
  160. char             kbd_macro3[LINE_LENGTH];
  161. char             kbd_macro4[LINE_LENGTH];
  162. char             kbd_macro5[LINE_LENGTH];
  163. char             kbd_macro6[LINE_LENGTH];
  164. char             kbd_macro7[LINE_LENGTH];
  165. char             kbd_macro8[LINE_LENGTH];
  166. char             kbd_macro9[LINE_LENGTH];
  167.  
  168. char            *kbd_macro_list[9] = {
  169.                     kbd_macro1,
  170.                     kbd_macro2,
  171.                     kbd_macro3,
  172.                     kbd_macro4,
  173.                     kbd_macro5,
  174.                     kbd_macro6,
  175.                     kbd_macro7,
  176.                     kbd_macro8,
  177.                     kbd_macro9
  178.                     };
  179.  
  180. char             *line_ptrs[MAX_LINES];
  181. int              line_sub = 0;
  182. int              curr_line = 0;
  183. int              disp_line = 0;
  184.  
  185. unsigned char    reg_fg = WHITE;
  186. unsigned char    reg_bg = BLUE;
  187. unsigned char    msg_fg = BLACK;
  188. unsigned char    msg_bg = CYAN;
  189. unsigned int     our_port = 1;
  190. unsigned int     our_speed = 1200;
  191. int              our_par = EV_PAR;
  192. int              our_bits = 7;
  193. int              our_stop = 1;
  194.  
  195. unsigned char    term_type = 1;
  196. unsigned char    term_type_save = 1;
  197. int              top_chat_x = 1;
  198. int              top_chat_y = 1;
  199. int              bottom_chat_x = 1;
  200. int              bottom_chat_y = 1;
  201. int              bottom_line = 25;
  202. unsigned char    screen_is_clear = TRUE;
  203. unsigned char    switch_to_chat  = FALSE;
  204. unsigned char    switch_from_chat= FALSE;
  205.  
  206. unsigned char    auto_answer = FALSE;
  207. unsigned char    set_answer  = FALSE;
  208.  
  209. char             phone_number[30] = "";
  210. int              dial_count = 0;
  211.  
  212. char             phone_num1 [81] = " ";
  213. char             phone_num2 [81] = " ";
  214. char             phone_num3 [81] = " ";
  215. char             phone_num4 [81] = " ";
  216. char             phone_num5 [81] = " ";
  217. char             phone_num6 [81] = " ";
  218. char             phone_num7 [81] = " ";
  219. char             phone_num8 [81] = " ";
  220. char             phone_num9 [81] = " ";
  221. char             phone_num10[81] = " ";
  222.  
  223. char             *phone_list[10] = {
  224.                     phone_num1,
  225.                     phone_num2,
  226.                     phone_num3,
  227.                     phone_num4,
  228.                     phone_num5,
  229.                     phone_num6,
  230.                     phone_num7,
  231.                     phone_num8,
  232.                     phone_num9,
  233.                     phone_num10
  234.                     };
  235.  
  236. char             no_carrier_msg [21] = "NO CARRIER";
  237. char             phone_busy [21] = "BUSY";
  238. char             dial_cmd   [21] = "ATD";
  239. char             modem_init [51] = "";
  240. char             modem_ok   [21] = "OK";
  241. char             modem_error[21] = "ERROR";
  242. char             hangup     [51] = "~+++~~ATH~|";
  243. char             connect_msg[21] = "CONNECT";
  244. char             answer_on  [21] = "~ATS0=1~|";
  245. char             answer_off [21] = "~ATS0=0~|";
  246.  
  247. int              sticky_menu  = 1;
  248. int              curr_item, old_item;
  249. unsigned char    dont_redraw = FALSE;
  250. int              item_recall[6] = {0, 0, 0, 0, 0, 0};
  251.  
  252. char    *dial_menu [13] = {
  253.                 " Phone Number 1           ",
  254.                 " Phone Number 2           ",
  255.                 " Phone Number 3           ",
  256.                 " Phone Number 4           ",
  257.                 " Phone Number 5           ",
  258.                 " Phone Number 6           ",
  259.                 " Phone Number 7           ",
  260.                 " Phone Number 8           ",
  261.                 " Phone Number 9           ",
  262.                 " Phone Number 10          ",
  263.                 " Manual Dial              ",
  264.                 " Load Phone Directory     ",
  265.                 " Hang Up                  "
  266.                         };
  267.  
  268. char    *file_menu [9] =  {
  269.                 " XModem Receive     ",
  270.                 " YModem Receive     ",
  271.                 " Kermit Receive     ",
  272.                 " Ascii Receive      ",
  273.                 " XModem Send        ",
  274.                 " YModem Send        ",
  275.                 " Kermit Send        ",
  276.                 " Ascii Send         ",
  277.                 " Capture       xxx  "
  278.                         };
  279.  
  280. char    *term_menu [2] = {
  281.                 " Normal        ",
  282.                 " Split (Chat)  "
  283.                         };
  284.  
  285. char    *modem_menu [9] = {
  286.                 " Comm. Port      x ",
  287.                 " Baud Rate   xxxxx ",
  288.                 " Data Bits       x ",
  289.                 " Parity       xxxx ",
  290.                 " Stop Bits       x ",
  291.                 " Local Echo    xxx ",
  292.                 " XON/XOFF      xxx ",
  293.                 " Add LineFeeds xxx ",
  294.                 " Auto Answer   xxx "
  295.                         };
  296.  
  297. char    *exit_menu[2] = {
  298.                 " Stay Ready ",
  299.                 " Unload     "
  300.                         };
  301.  
  302. char    *help_menu [7] = {
  303.                 " General       ",
  304.                 " Dialing       ",
  305.                 " Sending Files ",
  306.                 " Receiving     ",
  307.                 " Configuration ",
  308.                 " Modem Control ",
  309.                 " Scrolling     "
  310.                          };
  311.  
  312. char    *xfr_box [3] = {
  313.               "┌───────────────────────────────────────┐",
  314.               "│                                       │",
  315.               "└───────────────────────────────────────┘"
  316.                      };
  317.  
  318. char    *ascii_box [3] = {
  319. "┌──────────────────────────────────────────────────────────────────────────────┐",
  320. "│                                                                              │",
  321. "└──────────────────────────────────────────────────────────────────────────────┘"
  322.                         };
  323. int     oldx, oldy, did_ascii_xfr;
  324.  
  325. unsigned char    key_char;
  326. unsigned char    extended_char;
  327. unsigned char    curr_row, curr_col;
  328. unsigned char    capturing = FALSE;
  329. int              capture_handle = -1;
  330.  
  331. int              last_char = 0;
  332.  
  333. volatile unsigned char    transferring_file = FALSE;
  334. volatile unsigned char    stats_in_progress = FALSE;
  335. volatile unsigned char    transfer_init = FALSE;
  336. volatile unsigned char    transfer_type = NO_TRANSFER;
  337.  
  338. unsigned char    break_flag = FALSE;
  339. char             bs_str[4] = {BS, ' ', BS, 0};
  340. char             spaces[5] = "    ";
  341.  
  342. volatile int     tail     = 0;
  343. volatile int     head     = 0;
  344. volatile int     out_head = 0;
  345. volatile int     out_tail = 0;
  346.  
  347. volatile unsigned char output_queue_empty = TRUE;
  348.  
  349. unsigned char   iir_val  = 0;
  350. int             gap1     = 0;
  351. int             gap2     = 0;
  352. int             gap3     = 0;
  353. unsigned char   flow_control = FALSE;
  354. unsigned char   busy     = FALSE;
  355.  
  356. long            timeout  = 0l;
  357. int             port_base= 0;
  358. int             port_id  = 0;
  359. unsigned int    speedsave;
  360.  
  361. int     paritysave, bitssave, stop_bitsave;
  362. int     old_parity, old_bits, old_stop;
  363.  
  364. unsigned char    re_open_flag= FALSE;
  365. unsigned char    flag_save   = FALSE;
  366. unsigned char    echo_flag   = FALSE;
  367. unsigned char    crlf_for_cr = FALSE;
  368. unsigned char    send_crlf   = FALSE;
  369.  
  370. unsigned int     char_delay  = 0;
  371. unsigned int     line_delay  = 0;
  372.  
  373. int     THR      = 0;
  374. int     IER      = 0;
  375. int     IIR      = 0;
  376. int     LCR      = 0;
  377. int     MCR      = 0;
  378. int     LSR      = 0;
  379. int     MSR      = 0;
  380. int     DLAB_LO  = 0;
  381. int     DLAB_HI  = 0;
  382.  
  383. int             app_cursor_save;
  384. int             app_cursor_type;
  385. int             our_cursor_save;
  386. int             our_cursor_type;
  387. unsigned        vidmode;
  388. unsigned char   curr_vid_mode;
  389.  
  390. char            app_screen [4000];
  391. char            our_screen [4000];
  392.  
  393. int             transfer_handle;
  394. char            filename[50] = "";
  395.  
  396. unsigned int    x_index;
  397. int             eot_processed;
  398. char            nak_char;
  399. char            soh_char;
  400. char            prev_char;
  401. unsigned char   chksum;
  402. unsigned int    crc;
  403. unsigned int    xfr_size;
  404.  
  405. volatile unsigned char   xfr_abort    = FALSE;
  406. volatile unsigned char   user_abort   = FALSE;
  407.  
  408. unsigned char            EOF_flag     = FALSE;
  409. unsigned char            waiting_for_1st_nak = FALSE;
  410.  
  411. volatile unsigned        blocks_to_send;
  412. volatile unsigned        errors_this_block;
  413. volatile unsigned        error_count;
  414. volatile unsigned        block_count;
  415. volatile unsigned long   byte_count;
  416. volatile unsigned long   file_bytes;
  417.  
  418. unsigned short crctab[256] = {
  419.     0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
  420.     0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
  421.     0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
  422.     0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
  423.     0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
  424.     0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
  425.     0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
  426.     0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
  427.     0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
  428.     0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
  429.     0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
  430.     0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
  431.     0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
  432.     0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
  433.     0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
  434.     0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
  435.     0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
  436.     0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
  437.     0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
  438.     0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
  439.     0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
  440.     0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
  441.     0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
  442.     0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
  443.     0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
  444.     0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
  445.     0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
  446.     0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
  447.     0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
  448.     0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
  449.     0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
  450.     0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
  451. };
  452.  
  453. #define updcrc(crc,ch) (crctab[((crc >> 8) & 0xFF)] ^ (crc << 8) ^ ch)
  454.  
  455. char            xmodem_area[1024+1+2+2];
  456. char            modem_buff[SBUFSIZ];
  457. char            outbuff[OBUFSIZ];
  458. unsigned        *our_stack;
  459.  
  460. /* -------------------------------------------------- */
  461.  
  462.  
  463. /*
  464.  *
  465.  *      Kermit stuff
  466.  *
  467.  */
  468.  
  469.  
  470. /* Symbol Definitions */
  471.  
  472. #define MAXPACKSIZ  94      /* Maximum packet size */
  473. #define SP          32      /* ASCII space */
  474. #define DEL         127     /* Delete (rubout) */
  475. #define ESCCHR      '^'     /* Default escape character for CONNECT */
  476.  
  477. #define MAXTRY      10      /* Times to retry a packet */
  478. #define MYQUOTE     '#'     /* Quote character I will use */
  479. #define MYPAD       0       /* Number of padding characters I will need */
  480. #define MYPCHAR     0       /* Padding character I need (NULL) */
  481.  
  482. #define MYEOL       '\n'    /* End-Of-Line character I need */
  483.  
  484. #define MYTIME      10      /* Seconds after which I should be timed out */
  485. #define MAXTIM      60      /* Maximum timeout interval */
  486. #define MINTIM      2       /* Minumum timeout interval */
  487.  
  488.  
  489. /* Macro Definitions */
  490.  
  491. /*
  492.  * tochar: converts a control character to a printable one by adding a space.
  493.  *
  494.  * unchar: undoes tochar.
  495.  *
  496.  * ctl:    converts between control characters and printable characters by
  497.  *         toggling the control bit (ie. ^A becomes A and A becomes ^A).
  498.  */
  499.  
  500. #define tochar(ch)  ((ch) + ' ')
  501. #define unchar(ch)  ((ch) - ' ')
  502. #define ctl(ch)     ((ch) ^ 64 )
  503.  
  504.  
  505. int     _sizedata,          /* Size of present data */
  506.         _spsiz,             /* Maximum send packet size */
  507.         _pad,               /* How much padding to send */
  508.         _packnum,           /* Packet number */
  509.         _oldtry,            /* Times previous packet retried */
  510.         _times_up,          /* Timeout signal to 'rpack()' */
  511.         _remote,            /* -1 means we're a _remote kermit */
  512.         _image,             /* -1 means 8-bit mode */
  513.         _timint,            /* Timeout for foreign host on sends */
  514.         _filnamcnv,         /* -1 means do file name case conversions */
  515.         _filecount,         /* Number of files left to send */
  516.         rpack_done;         /* True if 'rpack()' did a complete packet */
  517.  
  518. char    _state,              /* Present state of the automaton */
  519.         _padchar,            /* Padding character to send */
  520.         _eol,                /* End-Of-Line character to send */
  521.         _escchr,             /* Connect command escape character */
  522.         _quote,              /* Quote character in incoming data */
  523.         **_filelist,         /* List of files to be sent */
  524.         kermit_path[80],     /* drive:\directory\ for receive */
  525.         _recpkt[101],        /* Receive packet buffer */
  526.         _packet[101];        /* Packet buffer */
  527.  
  528. char    *name_area;
  529. char    *name_ptrs[25];
  530.  
  531.  
  532.  
  533. /* mouse stuff */
  534.  
  535. unsigned char mouse_exists   = FALSE;
  536. unsigned char mouse_shared   = FALSE;
  537.  
  538. int         num_buttons    = 0;
  539. int         mouse_menu_x   = 0;
  540. unsigned    mouse_status   = 0;
  541. unsigned    mouse_column   = 0;
  542. unsigned    mouse_row      = 0;
  543. unsigned    left_button_x  = 0;
  544. unsigned    left_button_y  = 0;
  545. unsigned    mouse_x_save   = 39;
  546. unsigned    mouse_y_save   = 12;
  547.  
  548. /* -------------------------------- */
  549.  
  550. int     DosCancel(void)
  551.         {
  552.         critical_error = FALSE;
  553.         if (!in_popup)
  554.             return TRUE;
  555.  
  556.         beep();
  557.         delay(100);
  558.         beep();
  559.  
  560.         ask_yn("I/O error!  Cancel the file activity?");
  561.         if (key_char == 'y')
  562.             return TRUE;
  563.  
  564.         return FALSE;
  565.         }
  566.  
  567. int     DosOpen(char *name, unsigned char mode)
  568.         {
  569. retry_open:
  570.         crit_err_occurred = FALSE;
  571.  
  572.         _DX = (unsigned) name;
  573.         _AL = mode;
  574.         _AH = 0x3D;
  575.  
  576.         geninterrupt(0x21);
  577.  
  578.         temp1 = _AX;
  579.         asm   pushf
  580.         asm   pop   temp2
  581.  
  582.         if (critical_error)
  583.             {
  584.             if (!DosCancel()) goto retry_open;
  585.             crit_err_occurred = TRUE;
  586.             return -1;
  587.             }
  588.  
  589.         if ( (temp2 & 0x0001) == 0x0001 )
  590.             return -1;
  591.  
  592.         return temp1;
  593.         }
  594.  
  595. int     DosRead(int handle, char *buffer, unsigned count)
  596.         {
  597. retry_read:
  598.         _DX = (unsigned) buffer;
  599.         _CX = count;
  600.         _BX = handle;
  601.         _AH = 0x3F;
  602.  
  603.         geninterrupt(0x21);
  604.  
  605.         temp1 = _AX;
  606.         asm   pushf
  607.         asm   pop   temp2
  608.  
  609.         if (critical_error)
  610.             {
  611.             if (!DosCancel()) goto retry_read;
  612.             return -1;
  613.             }
  614.  
  615.         if ( (temp2 & 0x0001) == 0x0001 )
  616.             return -1;
  617.  
  618.         return temp1;
  619.         }
  620.  
  621. int     DosWrite(int handle, char *buffer, unsigned count)
  622.         {
  623. retry_write:
  624.         _DX = (unsigned) buffer;
  625.         _CX = count;
  626.         _BX = handle;
  627.         _AH = 0x40;
  628.  
  629.         geninterrupt(0x21);
  630.  
  631.         temp1 = _AX;
  632.         asm   pushf
  633.         asm   pop   temp2
  634.  
  635.         if (critical_error)
  636.             {
  637.             if (!DosCancel()) goto retry_write;
  638.             return -1;
  639.             }
  640.  
  641.         if ( (temp2 & 0x0001) == 0x0001 
  642.             || temp1 != count )
  643.                 return -1;
  644.  
  645.         return temp1;
  646.         }
  647.  
  648. int     DosCreate(char *name)
  649.         {
  650. retry_create:
  651.         crit_err_occurred = FALSE;
  652.  
  653.         _DX = (unsigned) name;
  654.         _CX = 0;
  655.         _AH = 0x3C;
  656.  
  657.         geninterrupt(0x21);
  658.  
  659.         temp1 = _AX;
  660.         asm   pushf
  661.         asm   pop   temp2
  662.  
  663.         if (critical_error)
  664.             {
  665.             if (!DosCancel()) goto retry_create;
  666.             crit_err_occurred = TRUE;
  667.             return -1;
  668.             }
  669.  
  670.         if ( (temp2 & 0x0001) == 0x0001)
  671.             return -1;
  672.  
  673.         return temp1;
  674.         }
  675.  
  676. int     DosClose(int handle)
  677.         {
  678.         _BX = handle;
  679.         _AH = 0x3E;
  680.  
  681.         geninterrupt(0x21);
  682.  
  683.         critical_error = FALSE;
  684.         return 0;
  685.         }
  686.  
  687. void    DosSeekEOF(unsigned handle)
  688.         {
  689.         _CX = 0;
  690.         _DX = 0;
  691.         _BX = handle;
  692.         _AX = 0x4202;
  693.  
  694.         geninterrupt(0x21);
  695.         }
  696.  
  697. void    DosSeekBackOne(unsigned handle)
  698.         {
  699.         _CX = 0;
  700.         _DX = 0;
  701.         _BX = handle;
  702.         _AX = 0x4202;
  703.         geninterrupt(0x21);
  704.  
  705.         _CX = _DX;
  706.         _DX = _AX - 1;
  707.         _BX = handle;
  708.         _AX = 0x4200;
  709.  
  710.         geninterrupt(0x21);
  711.         }
  712.  
  713. /* ------------------------------------ */
  714.  
  715. void    mouse_init(void)
  716.         {
  717.         void far * far *iv;
  718.  
  719.         iv = MK_FP(0x0000, 0x00CC);
  720.         if (FP_SEG(*iv) == 0x0000)
  721.             {
  722.             mouse_exists = 0;
  723.             num_buttons  = 0;
  724.             }
  725.         else
  726.             {
  727.             _AX = 0;
  728.             geninterrupt(0x33);
  729.             mouse_exists = _AX;
  730.             num_buttons  = _BX;
  731.             }
  732.         }
  733.  
  734. void    show_mouse (void)
  735.         {
  736.         _AX = 1;
  737.         geninterrupt(0x33);
  738.         } 
  739.  
  740. void    hide_mouse (void)
  741.         {
  742.         _AX = 2;
  743.         geninterrupt(0x33);
  744.         }
  745.  
  746. void    get_mouse (void)
  747.         {
  748.         unsigned  b, c, d;
  749.  
  750.         _AX = 3;
  751.         geninterrupt(0x33);
  752.         b = _BX;
  753.         c = _CX;
  754.         d = _DX;
  755.         mouse_status = b;
  756.         mouse_column = (c / 8) + 1;
  757.         mouse_row    = (d / 8) + 1;
  758.         }
  759.  
  760. void    move_mouse (int new_col, int new_row)
  761.         {
  762.         unsigned  a, c, d;
  763.  
  764.         a   = 4;
  765.         c   = (new_col - 1) * 8;
  766.         d   = (new_row - 1) * 8;
  767.         _AX = a;
  768.         _CX = c;
  769.         _DX = d;
  770.         geninterrupt(0x33);
  771.         }
  772.  
  773. int     left_button_down(void)
  774.         {
  775.         unsigned    b, c, d;
  776.  
  777.         _AX = 3;
  778.         geninterrupt(0x33);
  779.         b = _BX; c = _CX; d = _DX;
  780.         left_button_x = (c / 8) + 1;
  781.         left_button_y = (d / 8) + 1;
  782.         if ( (b & 0x01) == 0x01) return TRUE;
  783.         return FALSE;
  784.         }
  785.  
  786. int     left_button_up(void)
  787.         {
  788.         unsigned    b, c, d;
  789.  
  790.         _AX = 6;
  791.         _BX = 0;
  792.         geninterrupt(0x33);
  793.         b = _BX; c = _CX; d = _DX;
  794.         left_button_x = (c / 8) + 1;
  795.         left_button_y = (d / 8) + 1;
  796.         if (b > 0) return TRUE;
  797.         return FALSE;
  798.         }
  799.  
  800. int     right_button_up(void)
  801.         {
  802.         unsigned    b;
  803.  
  804.         _AX = 6;
  805.         _BX = 1;
  806.         geninterrupt(0x33);
  807.         b = _BX;
  808.         if (b > 0) return TRUE;
  809.         return FALSE;
  810.         }
  811.  
  812. /* -------------------------------------------------- */
  813.  
  814.  
  815. void    interrupt com_int (void)
  816.         { 
  817.         enable();
  818.  
  819.         _DX = inportb (LSR);        /* clear error conditions */
  820.  
  821. get_int_id:
  822.         iir_val = inportb (IIR);
  823.  
  824. /*******************************************
  825.  *      if ( (iir_val & 0x01) == 0x01 )
  826.  *          goto do_eoi;
  827.  ******************************************/
  828.  
  829.         if ( (iir_val & 0x04) == 0x04 )
  830.             goto handle_rdr;
  831.         if ( (iir_val & 0x02) == 0x02 )
  832.             goto handle_thre;
  833.  
  834.         goto do_eoi;
  835.  
  836. handle_thre:
  837.         disable();
  838.         if (out_head == out_tail)
  839.             {
  840.             output_queue_empty = TRUE;
  841.             enable();
  842.             goto get_int_id;
  843.             }
  844.  
  845.         outportb(THR, outbuff[out_tail]);
  846.         if (++out_tail == OBUFSIZ)
  847.             out_tail = 0;
  848.         enable();
  849.  
  850.         goto get_int_id;
  851.  
  852.  
  853. handle_rdr:
  854.         modem_buff[head] = inportb (THR);
  855.         if (++head == SBUFSIZ)
  856.             head  = 0;
  857.  
  858.         modem_buff[head] = 0;
  859.  
  860.         if (!flow_control || busy || transfer_type > 10)
  861.             goto get_int_id;
  862.  
  863.         gap1 = (head<tail) ? (SBUFSIZ-tail)+head : head-tail;
  864.         if (gap1 < HWM)
  865.             goto get_int_id;
  866.         busy = TRUE;
  867.  
  868.         timeout = 0x000fffffl;
  869.         while ( (inportb(LSR) & 0x20) == 0 && --timeout > 0l )
  870.             ;
  871.  
  872.         disable ();
  873.         outportb(THR, XOFF);
  874.         enable ();
  875.         goto get_int_id;
  876.  
  877. do_eoi:
  878.         outportb (ICR, EOI);
  879.         }
  880.  
  881. /* -------------------------------- */
  882.  
  883. int     get_modem(void)
  884.         { 
  885.         int res, x;
  886.  
  887.         if (transfer_type > 10)
  888.             {
  889.             if (tail == head) return (-1);
  890.             res = (int) modem_buff[tail];
  891.             if (++tail == SBUFSIZ) tail = 0;
  892.             return(res);
  893.             }
  894.  
  895.         if (crlf_for_cr && last_char == CR)
  896.             {
  897.             res = LINEFEED;
  898.             }
  899.         else
  900.             {
  901.             if (tail == head) return (-1);
  902.             res = (int) modem_buff[tail];
  903.             if (++tail == SBUFSIZ) tail = 0;
  904.             }
  905.  
  906.         if (capturing)
  907.             {
  908.             ch = (unsigned char) res;
  909.  
  910.             if (ch >= 32 
  911.                 || ch == LINEFEED || ch == FORMFEED || ch == CR)
  912.                     io_len = DosWrite(capture_handle, &ch, 1);
  913.             else
  914.             if (ch == TAB)
  915.                 io_len = DosWrite(capture_handle, spaces, 4);
  916.             else
  917.             if (ch == BS)
  918.                 DosSeekBackOne(capture_handle);
  919.             else
  920.                 goto save_last_char;
  921.  
  922.             if (io_len == -1)
  923.                 {
  924.                 capturing = FALSE;
  925.                 }
  926.             }
  927.  
  928. save_last_char:
  929.         last_char = res;
  930.  
  931.         if ( res == LINEFEED 
  932.             || (wherex() == 79 && res != CR && res != BS) )
  933.             {
  934.             line_ptrs[line_sub] = &modem_buff[tail];
  935.             if (tail > SBUFSIZ - 100 || line_sub == MAX_LINES - 2)
  936.                 {
  937.                 for (x=0; x<MAX_LINES; x++)
  938.                     line_ptrs[x] = line_ptrs[x+1];
  939.                 --line_sub;
  940.                 }
  941.             curr_line = disp_line = line_sub;
  942.             line_ptrs[++line_sub] = NULL;
  943.             }
  944.  
  945.         if (strlen(holdstr) < LINE_LENGTH - 1)
  946.             holdstr[strlen(holdstr)] = (char) res;
  947.         else
  948.             {
  949.             for (i=0; i<LINE_LENGTH; i++)
  950.                 holdstr[i] = holdstr[i+1];
  951.             holdstr[LINE_LENGTH - 1] = (char) res;
  952.             }
  953.  
  954.         if (!busy) goto get_modem_exit;
  955.  
  956.         gap2 = (head<tail) ? (SBUFSIZ-tail)+head : head-tail;
  957.         if (gap2 > LWM)
  958.             goto get_modem_exit;
  959.  
  960.         timeout = 0x000fffffl;
  961.         while ( (inportb(LSR) & 0x20) == 0 && --timeout > 0l )
  962.             ;
  963.  
  964.         disable ();
  965.         outportb(THR, XON);
  966.         enable ();
  967.         busy = FALSE;
  968.  
  969. get_modem_exit:
  970.         return (res);
  971.         }
  972.  
  973. void    purge_buffer(void)
  974.         {
  975.         delay(1000);
  976.         while ( (get_modem()) != -1 )
  977.             ;
  978.         }
  979.  
  980. void    send_break(void)
  981.         {
  982.         c = inportb(LCR);
  983.         outportb(LCR, (c | 0x40));
  984.         delay(break_milliseconds);
  985.         outportb(LCR, c);
  986.         break_flag = FALSE;
  987.         }
  988.  
  989. void    com_enable (void)
  990.         {
  991.         switch (port_id)
  992.             {
  993.             case 1 : 
  994.                 {
  995.                 setvect(0x0c, com_int);
  996.                 vectsave = getvect(0x0c);
  997.                 c = inportb(IMR) & IRQ4;
  998.                 break;
  999.                 }
  1000.             case 2 : 
  1001.                 {
  1002.                 setvect(0x0b, com_int);
  1003.                 vectsave = getvect(0x0b);
  1004.                 c = inportb(IMR) & IRQ3;
  1005.                 break;
  1006.                 }
  1007.             case 3 : 
  1008.                 {
  1009.                 setvect(0x0c, com_int);
  1010.                 vectsave = getvect(0x0c);
  1011.                 c = inportb(IMR) & IRQ4;
  1012.                 break;
  1013.                 }
  1014.             case 4 : 
  1015.                 {
  1016.                 setvect(0x0b, com_int);
  1017.                 vectsave = getvect(0x0b);
  1018.                 c = inportb(IMR) & IRQ3;
  1019.                 break;
  1020.                 }
  1021.             default : break;
  1022.             }
  1023.  
  1024.         disable();
  1025.         outportb(IER, RX_INT);
  1026.         outportb(MCR, RTS | DTR | OUT2);
  1027.         outportb(IMR, c);
  1028.         enable();
  1029.         }
  1030.  
  1031. void    drop_dtr(void)
  1032.         {
  1033.         outportb(MCR, 0);
  1034.         delay(250);
  1035.         outportb(MCR, RTS | DTR | OUT2);
  1036.         }
  1037.  
  1038. void    close_port(void)
  1039.         {
  1040.         disable();
  1041.         c = inportb(IMR);
  1042.         outportb(MCR, 0);
  1043.         outportb(IER, 0);
  1044.         switch (port_id)
  1045.             {
  1046.             case 1 : c |= ~IRQ4; setvect(0x0c, oldint0c); break;
  1047.             case 2 : c |= ~IRQ3; setvect(0x0b, oldint0b); break;
  1048.             case 3 : c |= ~IRQ4; setvect(0x0c, oldint0c); break;
  1049.             case 4 : c |= ~IRQ3; setvect(0x0b, oldint0b); break;
  1050.             default: break;
  1051.             }
  1052.         outportb(IMR, c);
  1053.         enable();
  1054.         vectsave = NULL;
  1055.         port_id  = 0;
  1056.         }
  1057.  
  1058. void    send_char (char x)
  1059.         {
  1060.         do
  1061.             gap3 = (out_head<out_tail)? 
  1062.                 (OBUFSIZ-out_tail)+out_head : out_head-out_tail;
  1063.             while (gap3 > (OBUFSIZ / 4) * 3);
  1064.  
  1065.         if (echo_flag && transfer_type < 10 && x != XON && x != XOFF)
  1066.             {
  1067.             disable();
  1068.             modem_buff[head] = x;
  1069.             if (++head == SBUFSIZ)
  1070.                 head  = 0;
  1071.             modem_buff[head] = 0;
  1072.             enable();
  1073.             }
  1074.  
  1075.         disable();
  1076.  
  1077.         if (output_queue_empty)
  1078.             {
  1079.             outportb(THR, x);
  1080.             output_queue_empty = FALSE;
  1081.             enable();
  1082.             return;
  1083.             }
  1084.  
  1085.         outbuff [out_head] = x;
  1086.         if (++out_head == OBUFSIZ)
  1087.             out_head  = 0;
  1088.         enable ();
  1089.         }
  1090.  
  1091.  
  1092.  
  1093. void    send_string (char *s)
  1094.         {
  1095.         while (*s)
  1096.             {
  1097.             if (*s == '~')
  1098.                 delay(950);
  1099.             else
  1100.             if (*s == '|')
  1101.                 send_char(CR);
  1102.             else
  1103.                 send_char(*s);
  1104.             delay(10);
  1105.             s++;
  1106.             }
  1107.         }
  1108.  
  1109. int     carrier(void)
  1110.         {
  1111.         if (!use_carrier) return call_in_progress;
  1112.  
  1113.         inportb(MSR);
  1114.         return ( (int) ( (inportb(MSR) >> 7) & 0x01) );
  1115.         }
  1116.  
  1117.  
  1118. int     set_port (int port)
  1119.         {
  1120.         int far   *RS232_addr;
  1121.  
  1122.         switch (port)
  1123.             { 
  1124.             case 1 : RS232_addr=MK_FP(0x0040, 0);
  1125.                      port_base = *RS232_addr;
  1126.                      break;
  1127.             case 2 : RS232_addr=MK_FP(0x0040, 2); 
  1128.                      port_base = *RS232_addr;
  1129.                      break;
  1130.             case 3 : port_base = 0x03E8;
  1131.                      break;
  1132.             case 4 : port_base = 0x02E8;
  1133.                      break;
  1134.             default : return (-1);
  1135.             }
  1136.  
  1137.         if (port < 3 && *RS232_addr == 0) 
  1138.             return (-1);
  1139.  
  1140.         port_id = port;
  1141.         THR     = port_base;
  1142.         IER     = port_base + 1;
  1143.         IIR     = port_base + 2;
  1144.         LCR     = port_base + 3;
  1145.         MCR     = port_base + 4;
  1146.         LSR     = port_base + 5;
  1147.         MSR     = port_base + 6;
  1148.         DLAB_HI = port_base + 1;
  1149.         DLAB_LO = port_base;
  1150.  
  1151.         inportb(THR);
  1152.         inportb(LSR);
  1153.  
  1154.         return (0);
  1155.         }
  1156.  
  1157. int     set_speed (unsigned int speed)
  1158.         {
  1159.         char      c;
  1160.         unsigned  divisor;
  1161.  
  1162.         if (speed < 1 || speed > MAX_BAUD) return (-1);
  1163.  
  1164.         divisor = (unsigned) (115200l/speed);
  1165.         disable ();
  1166.         c=inportb (LCR);
  1167.         outportb  (LCR, (c | 0x80));
  1168.         outportb  (DLAB_LO, (divisor & 0x00ff));
  1169.         outportb  (DLAB_HI, ((divisor>>8) & 0x00ff));
  1170.         outportb  (LCR, c);
  1171.         enable();
  1172.         speedsave = speed;
  1173.         return (0);
  1174.         }
  1175.  
  1176. int     set_parms (int parity, int bits, int stop_bit)
  1177.         {
  1178.         int temp;
  1179.  
  1180.         if ((parity < NO_PAR) || (parity > OD_PAR)) return (-1);
  1181.         if ((bits < 5) || (bits > 8)) return (-1);
  1182.         if ((stop_bit < 1) || (stop_bit > 2)) return (-1);
  1183.  
  1184.         temp = bits - 5;
  1185.         temp|= ((stop_bit == 1) ? 0x00 : 0x04);
  1186.         switch (parity)
  1187.             { 
  1188.             case NO_PAR : temp |= 0x00; break;
  1189.             case OD_PAR : temp |= 0x08; break;
  1190.             case EV_PAR : temp |= 0x18; break;
  1191.             }
  1192.  
  1193.         disable();
  1194.         outportb (LCR, temp);
  1195.         enable();
  1196.         paritysave   = parity;
  1197.         bitssave     = bits;
  1198.         stop_bitsave = stop_bit;
  1199.         return (0);
  1200.         }
  1201.  
  1202. int     open_port(int port,unsigned speed,int parity,int bits,int stop_bit)
  1203.         {
  1204.         if (set_port(port) == -1)   return(-1);
  1205.  
  1206.         if (set_speed(speed) == -1) return(-1);
  1207.  
  1208.         if (set_parms(parity, bits, stop_bit) == -1) return (-1);
  1209.  
  1210.         com_enable();
  1211.         return (0);
  1212.         }
  1213.  
  1214. /* -------------------------------------------------- */
  1215.  
  1216. int     sk_loaded(void)
  1217.         {
  1218.         asm     mov   ax, 0
  1219.         asm     mov   es, ax
  1220.         asm     mov   bx, 0020h
  1221.         asm     mov   dx, word ptr es:[bx]
  1222.         asm     mov   cx, word ptr es:[bx+2]
  1223.         asm     sub   dx, 4
  1224.         sk_ptr1 = MK_FP(_CX, _DX);
  1225.         if (*sk_ptr1 == 0x49424b53l) return TRUE;
  1226.  
  1227.         asm     mov   ax, 0
  1228.         asm     mov   es, ax
  1229.         asm     mov   bx, 0020h
  1230.         asm     mov   dx, word ptr es:[bx]
  1231.         asm     mov   cx, word ptr es:[bx+2]
  1232.         asm     sub   dx, 2
  1233.         sk_ptr2 = MK_FP(_CX, _DX);
  1234.         if (*sk_ptr2 == 0x4b53) return TRUE;
  1235.  
  1236.         return FALSE;
  1237.         }
  1238.  
  1239.  
  1240. void    interrupt int08(void)
  1241.     {
  1242.     in_int08 = TRUE;
  1243.     oldint08();
  1244.     tick_counter++;
  1245.     enable();
  1246.  
  1247.     if (!hot_flag && !de_install && !transferring_file)
  1248.         goto exit08;
  1249.  
  1250.     if (in_int09 || in_int10 || in_int13 || in_int16 || in_int28)
  1251.         goto exit08;
  1252.  
  1253.     if (*indos_ptr != 0)
  1254.          goto exit08;
  1255.  
  1256.     if (*indos2_ptr != 0)
  1257.          goto exit08;
  1258.  
  1259.     if (*prtsc_flag_ptr == 1)
  1260.          goto exit08;
  1261.  
  1262.     outportb(0x20, 0x0b);
  1263.     if (inportb(0x20)) goto exit08;
  1264.  
  1265.     if ( (hot_flag || de_install) && !in_popup && !in_background)
  1266.         {
  1267.         in_popup = TRUE;
  1268.         do_popup();
  1269.         in_popup = FALSE;
  1270.         }
  1271.     else
  1272.     if (transferring_file && !in_background && !in_popup)
  1273.         {
  1274.         in_background = TRUE;
  1275.         do_transfer();
  1276.         in_background = FALSE;
  1277.         }
  1278.  
  1279. exit08:
  1280.     in_int08 = FALSE;
  1281.     }
  1282.  
  1283. void interrupt  int09 (void)
  1284.     {
  1285.     in_int09 = TRUE;
  1286.     kbd_code = inportb(0x60);
  1287.     oldint09();
  1288.     enable();
  1289.  
  1290.     if (use_alt)
  1291.         if (kbd_code == (ALT | 0x80))
  1292.             if (prev_kbd_code == ALT)
  1293.                 if (in_popup)
  1294.                     alt_menu = TRUE;
  1295.  
  1296.     if (kbd_code != 0 && kbd_code != 0xE0)
  1297.         prev_kbd_code = kbd_code;
  1298.  
  1299.     if ( (*kbd_flag_ptr & 0x09) == 0x09 )
  1300.         {
  1301.         de_install = FALSE;
  1302.         hot_flag   = TRUE;
  1303.         goto int09_exit;
  1304.         }
  1305.  
  1306. int09_exit:
  1307.     in_int09 = FALSE;
  1308.     }
  1309.  
  1310. void    interrupt int10(unsigned bp,
  1311.                         unsigned di,
  1312.                         unsigned si,
  1313.                         unsigned ds,
  1314.                         unsigned es,
  1315.                         unsigned dx,
  1316.                         unsigned cx,
  1317.                         unsigned bx,
  1318.                         unsigned ax,
  1319.                         unsigned ip,
  1320.                         unsigned cs,
  1321.                         unsigned flags)
  1322.     {
  1323.     in_int10 = TRUE;
  1324.     enable();
  1325.  
  1326.     asm     push ds
  1327.     _DS   = ds;
  1328.     _AX   = ax;
  1329.  
  1330.     asm     push bp
  1331.     asm     pushf
  1332.     asm     cli
  1333.     asm     call    dword ptr cs:[0004h]
  1334.     asm     pop  bp
  1335.  
  1336.     asm     pushf
  1337.     asm     pop flags
  1338.  
  1339.     ax    = _AX;
  1340.     bx    = _BX;
  1341.     cx    = _CX;
  1342.     dx    = _DX;
  1343.     si    = _SI;
  1344.     di    = _DI;
  1345.     es    = _ES;
  1346.     ds    = _DS;
  1347.     asm     pop ds
  1348.  
  1349.     in_int10 = FALSE;
  1350.     }
  1351.  
  1352. void    interrupt int13(unsigned bp,
  1353.                         unsigned di,
  1354.                         unsigned si,
  1355.                         unsigned ds,
  1356.                         unsigned es,
  1357.                         unsigned dx,
  1358.                         unsigned cx,
  1359.                         unsigned bx,
  1360.                         unsigned ax,
  1361.                         unsigned ip,
  1362.                         unsigned cs,
  1363.                         unsigned flags)
  1364.     {
  1365.     in_int13 = TRUE;
  1366.     enable();
  1367.  
  1368.     asm     push ds
  1369.     _DS   = ds;
  1370.     _AX   = ax;
  1371.  
  1372.     asm     push bp
  1373.     asm     pushf
  1374.     asm     cli
  1375.     asm     call    dword ptr cs:[0008h]
  1376.     asm     pop  bp
  1377.  
  1378.     asm     pushf
  1379.     asm     pop flags
  1380.  
  1381.     ax    = _AX;
  1382.     bx    = _BX;
  1383.     cx    = _CX;
  1384.     dx    = _DX;
  1385.     si    = _SI;
  1386.     di    = _DI;
  1387.     es    = _ES;
  1388.     ds    = _DS;
  1389.     asm     pop ds
  1390.  
  1391.     in_int13 = FALSE;
  1392.     }
  1393.  
  1394. void    interrupt int16(unsigned bp,
  1395.                         unsigned di,
  1396.                         unsigned si,
  1397.                         unsigned ds,
  1398.                         unsigned es,
  1399.                         unsigned dx,
  1400.                         unsigned cx,
  1401.                         unsigned bx,
  1402.                         unsigned ax,
  1403.                         unsigned ip,
  1404.                         unsigned cs,
  1405.                         unsigned flags)
  1406.     {
  1407.     unsigned      temp_ax;
  1408.     unsigned char temp_ah;
  1409.  
  1410.     in_int16 = TRUE;
  1411.     enable();
  1412.  
  1413.     temp_ax = _AX;
  1414.     temp_ah = _AH;
  1415.  
  1416.     if (temp_ax == 'SN')
  1417.         {
  1418.         ax = 'sn';
  1419.         goto int16_exit;
  1420.         }
  1421.  
  1422.     if (in_popup)
  1423.         goto do_old16;
  1424.  
  1425.     if (temp_ah != 0)
  1426.         goto do_old16;
  1427.  
  1428. wait_for_key:
  1429.     _AH = 1;
  1430.     oldint16();
  1431.     asm     jz   popup_16 
  1432.  
  1433.     goto do_old16;
  1434.  
  1435. popup_16:
  1436.     if (!hot_flag && !de_install && !transferring_file)
  1437.         goto wait_for_key;
  1438.  
  1439.     if (in_int09 || in_int10 || in_int13 || in_int08 || in_int28)
  1440.         goto wait_for_key;
  1441.  
  1442.     if (*indos_ptr != 0)
  1443.          goto wait_for_key;
  1444.  
  1445.     if (*indos2_ptr != 0)
  1446.          goto wait_for_key;
  1447.  
  1448.     if (*prtsc_flag_ptr == 1)
  1449.          goto wait_for_key;
  1450.  
  1451.     outportb(0x20, 0x0b);
  1452.     if (inportb(0x20)) goto wait_for_key;
  1453.  
  1454.     if ( (hot_flag || de_install) && !in_popup && !in_background)
  1455.         {
  1456.         in_popup = TRUE;
  1457.         do_popup();
  1458.         in_popup = FALSE;
  1459.         }
  1460.     else
  1461.     if (transferring_file && !in_background && !in_popup)
  1462.         {
  1463.         in_background = TRUE;
  1464.         do_transfer();
  1465.         in_background = FALSE;
  1466.         }
  1467.  
  1468.     goto wait_for_key;
  1469.  
  1470.  
  1471. do_old16:
  1472.     _AX = temp_ax;
  1473.     oldint16();
  1474.     asm     pushf
  1475.     asm     pop flags
  1476.     ax    = _AX;
  1477.     bx    = _BX;
  1478.     cx    = _CX;
  1479.     dx    = _DX;
  1480.  
  1481. int16_exit:
  1482.     in_int16 = FALSE;
  1483.     }
  1484.  
  1485. void interrupt  int1b (void)
  1486.     {
  1487.     enable();
  1488.     break_flag = TRUE;
  1489.     }
  1490.  
  1491. void interrupt  int1c (void)
  1492.     {
  1493.     enable();
  1494.     }
  1495.  
  1496. void    interrupt int21(unsigned bp,
  1497.                         unsigned di,
  1498.                         unsigned si,
  1499.                         unsigned ds,
  1500.                         unsigned es,
  1501.                         unsigned dx,
  1502.                         unsigned cx,
  1503.                         unsigned bx,
  1504.                         unsigned ax,
  1505.                         unsigned ip,
  1506.                         unsigned cs,
  1507.                         unsigned flags)
  1508.     {
  1509.     enable();
  1510.     function_id = _AH;
  1511.  
  1512.     if ( function_id != 0x00
  1513.       && function_id != 0x31 
  1514.       && function_id != 0x4b 
  1515.       && function_id != 0x4c 
  1516.       && function_id != 0x44 
  1517.       && function_id != 0x2f 
  1518.       && function_id != 0x1a)
  1519.             goto carry_on;
  1520.  
  1521. skip_out:
  1522.     asm     mov     sp, bp
  1523.     asm     pop     bp
  1524.     asm     pop     di
  1525.     asm     pop     si
  1526.     asm     pop     ds
  1527.     asm     pop     es
  1528.     asm     pop     dx
  1529.     asm     pop     cx
  1530.     asm     pop     bx
  1531.     asm     pop     ax
  1532.  
  1533. /*  jmp dword ptr cs:[0]  */
  1534.     asm     db      02eh,0ffh,02eh,0000h,000h
  1535.  
  1536. carry_on:
  1537.     if (!sk_loaded() || *indos2_ptr == 0)
  1538.         goto skip_out;
  1539.  
  1540.     if (*indos_ptr == 0)
  1541.         in_int21 = FALSE;
  1542.  
  1543.     if (in_popup || in_int21)
  1544.         {
  1545.         pass_through = TRUE;
  1546.         goto do_the_call;
  1547.         }
  1548.  
  1549.     in_int21 = TRUE;
  1550.  
  1551. invoke_dos:
  1552.     if (   function_id != 0x01 
  1553.         && function_id != 0x07
  1554.         && function_id != 0x08
  1555.         && function_id != 0x0a
  1556.         && function_id != 0x0c)
  1557.         goto do_the_call;
  1558.  
  1559. wait_for_dos_key:
  1560.     _AH = 0x0b;
  1561.     asm     pushf
  1562.     asm     cli
  1563.     asm     call    dword ptr cs:[0000]
  1564.     if (_AL == 0)
  1565.         goto check_flags;
  1566.  
  1567. do_the_call:
  1568.     asm     push ds
  1569.     _AX   = ax;
  1570.     _BX   = bx;
  1571.     _CX   = cx;
  1572.     _DX   = dx;
  1573.     _SI   = si;
  1574.     _DI   = di;
  1575.     _ES   = es;
  1576.     _DS   = ds;
  1577.  
  1578.     asm     pushf
  1579.     asm     cli
  1580.     asm     call    dword ptr cs:[0000]
  1581.  
  1582.     asm     pushf
  1583.     asm     pop flags
  1584.  
  1585.     ax    = _AX;
  1586.     bx    = _BX;
  1587.     cx    = _CX;
  1588.     dx    = _DX;
  1589.     si    = _SI;
  1590.     di    = _DI;
  1591.     es    = _ES;
  1592.     ds    = _DS;
  1593.     asm     pop ds
  1594.  
  1595.     if (pass_through)
  1596.         {
  1597.         pass_through = FALSE;
  1598.         goto int21out;
  1599.         }
  1600.  
  1601.     if (   function_id == 0x01 
  1602.         || function_id == 0x07
  1603.         || function_id == 0x08
  1604.         || function_id == 0x0c)
  1605.             {
  1606.             in_int21   = FALSE;
  1607.             goto int21out;
  1608.             }
  1609.  
  1610. check_flags:
  1611.     if (!hot_flag && !transferring_file && !de_install)
  1612.         goto int21exit;
  1613.  
  1614.     if (*indos_ptr != 0)
  1615.         goto int21exit;
  1616.  
  1617.     if (*indos2_ptr != 0)
  1618.         goto int21exit;
  1619.  
  1620.     if (*prtsc_flag_ptr == 1)
  1621.         goto int21exit;
  1622.  
  1623.     outportb(0x20, 0x0b);
  1624.     if (inportb(0x20)) goto int21exit;
  1625.  
  1626.     if ( (hot_flag || de_install) && !in_popup && !in_background)
  1627.         {
  1628.         in_popup = TRUE;
  1629.         do_popup();
  1630.         in_popup = FALSE;
  1631.         }
  1632.     else
  1633.     if (transferring_file && !in_background && !in_popup)
  1634.         {
  1635.         in_background = TRUE;
  1636.         do_transfer();
  1637.         in_background = FALSE;
  1638.         }
  1639.  
  1640. int21exit:
  1641.     if (   function_id == 0x01 
  1642.         || function_id == 0x07
  1643.         || function_id == 0x08
  1644.         || function_id == 0x0a
  1645.         || function_id == 0x0c)
  1646.             goto wait_for_dos_key;
  1647.  
  1648.     in_int21 = FALSE;
  1649.  
  1650. int21out:
  1651.     ;
  1652.     }
  1653.  
  1654. void interrupt  int23 (void)
  1655.     {
  1656.     enable();
  1657.     }
  1658.  
  1659.  
  1660. void    interrupt int24(unsigned bp,
  1661.                         unsigned di,
  1662.                         unsigned si,
  1663.                         unsigned ds,
  1664.                         unsigned es,
  1665.                         unsigned dx,
  1666.                         unsigned cx,
  1667.                         unsigned bx,
  1668.                         unsigned ax,
  1669.                         unsigned ip,
  1670.                         unsigned cs,
  1671.                         unsigned flags)
  1672.     {
  1673.     temp1 = _AX;
  1674.     critical_error = TRUE;
  1675.  
  1676.     if (_osmajor < 3)
  1677.        ax = (temp1 & 0xFF00);
  1678.     else
  1679.        ax = (temp1 & 0xFF00) | 0x03;
  1680.     }
  1681.  
  1682.  
  1683. void    interrupt int28(void)
  1684.     {
  1685.     in_int28 = TRUE;
  1686.     oldint28();
  1687.     enable();
  1688.  
  1689.     if (!hot_flag && !de_install && !transferring_file)
  1690.         goto exit28;
  1691.  
  1692.     if (in_int09 || in_int10 || in_int13 || in_int16 || in_int08)
  1693.         goto exit28;
  1694.  
  1695.     if (*indos_ptr > 1)
  1696.          goto exit28;
  1697.  
  1698.     if (*indos2_ptr != 0)
  1699.          goto exit28;
  1700.  
  1701.     if (*prtsc_flag_ptr == 1)
  1702.          goto exit28;
  1703.  
  1704.     outportb(0x20, 0x0b);
  1705.     if (inportb(0x20)) goto exit28;
  1706.  
  1707.     if ( (hot_flag || de_install) && !in_popup && !in_background)
  1708.         {
  1709.         in_popup = TRUE;
  1710.         do_popup();
  1711.         in_popup = FALSE;
  1712.         }
  1713.     else
  1714.     if (transferring_file && !in_background && !in_popup)
  1715.         {
  1716.         in_background = TRUE;
  1717.         do_transfer();
  1718.         in_background = FALSE;
  1719.         }
  1720.  
  1721. exit28:
  1722.     in_int28 = FALSE;
  1723.     }
  1724.  
  1725. /* ------------------------------------------- */
  1726.  
  1727. void    beep(void)
  1728.         {
  1729.         sound(880);
  1730.         delay(100);
  1731.         nosound();
  1732.         }
  1733.  
  1734. void    cls(void)
  1735.         {
  1736.         if (mouse_exists) hide_mouse();
  1737.         if (term_type == CHAT)
  1738.             {
  1739.             window(1, 1, 80, 16);
  1740.             textcolor(reg_fg);
  1741.             textbackground(reg_bg);
  1742.             clrscr();
  1743.             window(1, 1, 80, 25);
  1744.             }
  1745.         else
  1746.             {
  1747.             clrscr();
  1748.             }
  1749.         gotoxy(1, 1);
  1750.         if (mouse_exists) show_mouse();
  1751.         screen_is_clear = TRUE;
  1752.         }
  1753.  
  1754. void    cls_bottom(void)
  1755.         {
  1756.         window(1, 17, 80, 25);
  1757.         textcolor(msg_fg);
  1758.         textbackground(msg_bg);
  1759.         clrscr();
  1760.         textcolor(reg_fg);
  1761.         textbackground(reg_bg);
  1762.         bottom_chat_x = bottom_chat_y = 1;
  1763.         gotoxy(1, 1);
  1764.         window(1, 1, 80, 25);
  1765.         }
  1766.  
  1767.  
  1768. void    save_screen(unsigned left, unsigned top,
  1769.                         unsigned right, unsigned bottom, char *buf,
  1770.                         int *curpos, int *curtype)
  1771.         {
  1772.         gettext(left, top, right, bottom, buf);
  1773.  
  1774.         _AH = 3;
  1775.         _BH = 0;
  1776.         geninterrupt(0x10);
  1777.         *curpos  = _DX;
  1778.         *curtype = _CX;
  1779.         }
  1780.  
  1781. void    restore_screen(unsigned left, unsigned top,
  1782.                         unsigned right, unsigned bottom, char *buf,
  1783.                         int *curpos, int *curtype)
  1784.         {
  1785.         puttext(left, top, right, bottom, buf);
  1786.  
  1787.         _DX = *curpos;
  1788.         curr_row = _DH + 1;
  1789.         curr_col = _DL + 1;
  1790.         _DX = *curpos;
  1791.         _AH = 2;
  1792.         _BH = 0;
  1793.         geninterrupt(0x10);
  1794.         _CX = *curtype;
  1795.         _AH = 1;
  1796.         geninterrupt(0x10);
  1797.         }
  1798.  
  1799. void    getkey(void)
  1800.         {
  1801.         int     k;
  1802.  
  1803.         if (!mouse_exists || break_flag) goto get_kbd_char;
  1804.  
  1805. kbd_mouse_loop:
  1806.         if (bioskey(1)) goto get_kbd_char;
  1807.  
  1808.         if ( left_button_up() )
  1809.             {
  1810.             key_char = CR;
  1811.             extended_char = 0;
  1812.             return;
  1813.             }
  1814.  
  1815.         if ( right_button_up() )
  1816.             {
  1817.             key_char = ESC;
  1818.             extended_char = 0;
  1819.             return;
  1820.             }
  1821.  
  1822.         goto kbd_mouse_loop;
  1823.  
  1824. get_kbd_char:
  1825.         k             = bioskey(0);
  1826.         key_char      = k & 0x00FF;
  1827.         extended_char = (k & 0xFF00) >> 8;
  1828.         }
  1829.  
  1830.  
  1831. int     kbdstring(char buff[], int max_chars)
  1832.         {
  1833.         int             i, j, insert_mode, ctype, res;
  1834.         unsigned char   row, col, trow, tcol;
  1835.         unsigned int    cblock;
  1836.  
  1837.         if (mouse_exists) hide_mouse();
  1838.         i = j = insert_mode = 0;
  1839.         if (get_vid_mode() == 7)
  1840.             cblock = 0x000D;
  1841.         else
  1842.             cblock = 0x0007;
  1843.  
  1844.         _AH = 3;
  1845.         _BH = 0;
  1846.         geninterrupt(0x10);
  1847.         ctype = _CX;
  1848.         col = wherex();
  1849.         row = wherey();
  1850.  
  1851.         textcolor(msg_fg);
  1852.         textbackground(msg_bg);
  1853.         cprintf("%-*s", max_chars-1, buff);
  1854.         gotoxy(col, row);
  1855.  
  1856. ks1:    getkey();
  1857.         tcol = wherex();
  1858.         trow = wherey();
  1859.  
  1860.         if (key_char == ESC)
  1861.             {
  1862.             buff[0] = '\0';
  1863.             res = 0;
  1864.             goto kbdstring_exit;
  1865.             }
  1866.  
  1867.         if (key_char == 0)
  1868.             {
  1869.             if (extended_char == INSKEY)
  1870.                 {
  1871.                 if (insert_mode)
  1872.                     {
  1873.                     insert_mode = FALSE;
  1874.                     _CX = ctype;
  1875.                     _AH = 1;
  1876.                     geninterrupt(0x10);
  1877.                     }
  1878.                 else
  1879.                     {
  1880.                     insert_mode = TRUE;
  1881.                     _CX = cblock;
  1882.                     _AH = 1;
  1883.                     geninterrupt(0x10);
  1884.                     }
  1885.                 }
  1886.             else
  1887.             if (extended_char == HOMEKEY)
  1888.                 {
  1889.                 i = 0;
  1890.                 gotoxy(col, row);
  1891.                 }
  1892.             else
  1893.             if (extended_char == ENDKEY)
  1894.                 {
  1895.                 i = strlen(buff);
  1896.                 gotoxy(col+strlen(buff), row);
  1897.                 }
  1898.             else
  1899.             if (extended_char == DELKEY)
  1900.                 {
  1901.                 for (j = i; j < strlen(buff); j++)
  1902.                     buff[j] = buff[j+1];
  1903.                 gotoxy(col, row);
  1904.                 textcolor(msg_fg);
  1905.                 textbackground(msg_bg);
  1906.                 cprintf("%-*s", max_chars-1, buff);
  1907.                 gotoxy(tcol, trow);
  1908.                 }
  1909.             else
  1910.             if (extended_char == RIGHTKEY)
  1911.                 {
  1912.                 if (i < strlen(buff))
  1913.                     {
  1914.                     i++;
  1915.                     gotoxy(tcol+1, trow);
  1916.                     }
  1917.                 }
  1918.             else
  1919.             if (extended_char == LEFTKEY)
  1920.                 {
  1921.                 if (i > 0)
  1922.                     {
  1923.                     i--;
  1924.                     gotoxy(tcol-1, trow);
  1925.                     }
  1926.                 }
  1927.             }
  1928.  
  1929.         if (key_char == 0)
  1930.             goto ks1;
  1931.  
  1932.         if (key_char == BS)
  1933.             {
  1934.             if (i > 0)
  1935.                 {
  1936.                 i--;
  1937.                 gotoxy(tcol-1, trow);
  1938.                 }
  1939.             }
  1940.  
  1941.         if (key_char == CR)
  1942.             {
  1943.             res = 0;
  1944.             goto kbdstring_exit;
  1945.             }
  1946.  
  1947.         if (key_char < 32)
  1948.             goto ks1;
  1949.  
  1950.         if (i == max_chars-1)
  1951.             goto ks1;
  1952.  
  1953.         if (insert_mode)
  1954.             {
  1955.             for (j = strlen(buff)-1; j >= i; j--)
  1956.                 if (j < max_chars-2)
  1957.                     buff[j+1] = buff[j];
  1958.             buff[i++] = key_char;
  1959.             _CX = ctype;
  1960.             _AH = 1;
  1961.             geninterrupt(0x10);
  1962.             gotoxy(col, row);
  1963.             textcolor(msg_fg);
  1964.             textbackground(msg_bg);
  1965.             cprintf("%-*s", max_chars-1, buff);
  1966.             gotoxy(++tcol, trow);
  1967.             _CX = cblock;
  1968.             _AH = 1;
  1969.             geninterrupt(0x10);
  1970.             }
  1971.         else
  1972.             {
  1973.             buff[i++] = key_char;
  1974.             textcolor(msg_fg);
  1975.             textbackground(msg_bg);
  1976.             cprintf("%c", key_char);
  1977.             }
  1978.  
  1979.         goto ks1;
  1980.  
  1981.  
  1982. kbdstring_exit:
  1983.         _CX = ctype;
  1984.         _AH = 1;
  1985.         geninterrupt(0x10);
  1986.  
  1987.         if (mouse_exists) show_mouse();
  1988.         return(res);
  1989.         }
  1990.  
  1991. /************************************/
  1992.  
  1993. int     fgetbuf(int fh)
  1994.         {
  1995. fgetbuf01:
  1996.         if (fbufndx < fbufbytes)
  1997.             return( (int) xmodem_area[fbufndx++]);
  1998.  
  1999.         io_len = DosRead(fh, xmodem_area, 1024);
  2000.         if (io_len == -1)
  2001.             {
  2002.             fbufndx = 2000;
  2003.             return(-1);
  2004.             }
  2005.  
  2006.         fbufbytes = io_len;
  2007.         if (fbufbytes == 0)
  2008.             {
  2009.             fbufndx = 2000;
  2010.             return(-1);
  2011.             }
  2012.  
  2013.         fbufndx = 0;
  2014.         goto fgetbuf01;
  2015.         }
  2016.  
  2017. /************************************/
  2018.  
  2019. int     fgetstring(int fh, char buff[], int max_chars)
  2020.         {
  2021.         int i, c;
  2022.  
  2023.         setmem(buff, max_chars, 0);
  2024.         i = 0;
  2025.  
  2026. fgs1:   if (i == max_chars - 1)
  2027.             {
  2028.             buff[i] = '\0';
  2029.             return(0);
  2030.             }
  2031.         if ( (c = fgetbuf(fh)) == -1 )
  2032.             {
  2033.             buff[i] = '\0';
  2034.             return(-1);
  2035.             }
  2036.         if (c == CR || c == CTRLZ)
  2037.             goto fgs1;
  2038.         if (c == LINEFEED)
  2039.             {
  2040.             buff[i] = '\0';
  2041.             return(0);
  2042.             }
  2043.  
  2044.         buff[i++] = (char) c;
  2045.         goto fgs1;
  2046.         }
  2047.  
  2048. void    ask_yn(char *s)
  2049.         {
  2050.         char    linsav[160];
  2051.         int     cpos, ctype;
  2052.         int     mx, my;
  2053.  
  2054.         if (mouse_exists) hide_mouse();
  2055.         save_screen(1,25,80,25, linsav, &cpos, &ctype);
  2056.         textcolor(msg_fg);
  2057.         textbackground(msg_bg);
  2058.         gotoxy(1, 25);
  2059.         cprintf("%-79.79s", " ");
  2060.  
  2061.         gotoxy(1, 25);
  2062.         cprintf("%s", s);
  2063.         if (mouse_exists) show_mouse();
  2064.  
  2065.         if (mouse_exists)
  2066.             {
  2067.             mx = wherex(); my = wherey();
  2068.             cprintf(" < YES >   < NO  >");
  2069.             }
  2070.         else
  2071.             {
  2072.             cprintf(" (y/n) ");
  2073.             }
  2074.  
  2075. ask10:  if (!mouse_exists) goto ayn_kbd;
  2076.  
  2077.         if ( left_button_up() )
  2078.             {
  2079.             if (left_button_y != my) goto ask10;
  2080.             if (left_button_x >= mx+1 && left_button_x <= mx+7)
  2081.                 {
  2082.                 key_char = 'y';
  2083.                 goto ayn_exit;
  2084.                 }
  2085.             if (left_button_x >= mx+11 && left_button_x <= mx+17)
  2086.                 {
  2087.                 key_char = 'n';
  2088.                 goto ayn_exit;
  2089.                 }
  2090.             goto ask10;
  2091.             }
  2092.  
  2093.         if (!bioskey(1)) goto ask10;
  2094.  
  2095. ayn_kbd:
  2096.         getkey();
  2097.         if ( key_char != 'y' && key_char != 'Y'
  2098.           && key_char != 'n' && key_char != 'N' )
  2099.             goto ask10;
  2100.  
  2101. ayn_exit:
  2102.         key_char |= 0x20;
  2103.         if (mouse_exists) hide_mouse();
  2104.         restore_screen(1,25,80,25, linsav, &cpos, &ctype);
  2105.         if (mouse_exists) show_mouse();
  2106.         textcolor(reg_fg);
  2107.         textbackground(reg_bg);
  2108.         }
  2109.  
  2110. void    message(char *s)
  2111.         {
  2112.         char    linsav[160];
  2113.         int     cpos, ctype;
  2114.  
  2115.         if (mouse_exists) hide_mouse();
  2116.         save_screen(1,25,80,25, linsav, &cpos, &ctype);
  2117.         textcolor(msg_fg);
  2118.         textbackground(msg_bg);
  2119.         gotoxy(1, 25);
  2120.  
  2121.         if (mouse_exists)
  2122.             cprintf("%-54.54s<Press a key or button.> ", s);
  2123.         else
  2124.             cprintf("%-64.64s<Press a key.> ", s);
  2125.  
  2126.         if (mouse_exists) show_mouse();
  2127.  
  2128.         getkey();
  2129.  
  2130.         if (mouse_exists) hide_mouse();
  2131.         restore_screen(1,25,80,25, linsav, &cpos, &ctype);
  2132.         if (mouse_exists) show_mouse();
  2133.         textcolor(reg_fg);
  2134.         textbackground(reg_bg);
  2135.         }
  2136.  
  2137.  
  2138. int     okay_to_unload(void)
  2139.         {
  2140.         next_mcb       = MK_FP( (ourpsp) + *our_mcb_size, 0);
  2141.         next_mcb_owner = MK_FP(  ourpsp  + *our_mcb_size, 1);
  2142.  
  2143.         if (  *next_mcb_owner == 0x0000
  2144.            || *next_mcb_owner == 0xffff
  2145.            || *next_mcb_owner <  ourpsp  )
  2146.                 if (!carrier())
  2147.                     return TRUE;
  2148.  
  2149.         return FALSE;
  2150.         }
  2151.  
  2152.  
  2153. void    show_help(int context)
  2154.         {
  2155.         int     help_handle, row, j;
  2156.         char    *p;
  2157.         char    str80[81];
  2158.         char    itemid[4];
  2159.         char    pageid[4];
  2160.  
  2161.         if ( (p = searchpath("comm.hlp")) == NULL || critical_error )
  2162.             {
  2163.             critical_error = FALSE;
  2164.             beep();
  2165.             message("ERROR.  'COMM.HLP' not found.");
  2166.             return;
  2167.             }
  2168.  
  2169.         term_type_save = term_type;
  2170.         term_type = NORMAL;
  2171.  
  2172.         strcpy(str80, p);
  2173.         help_handle = DosOpen(str80, 0);
  2174.         if (help_handle < 1)
  2175.             {
  2176.             beep();
  2177.             message("ERROR.  'COMM.HLP' not found.");
  2178.             return;
  2179.             }
  2180.  
  2181.         fbufndx      = 2000;
  2182.         fbufbytes    = 0;
  2183.  
  2184.         sprintf(itemid, "%1d", context);
  2185.         strcpy(pageid, "pg");
  2186.         strcat(pageid, itemid);
  2187.         i = fgetstring(help_handle, str80, 80);
  2188.         while (strcmp(str80, pageid) NE && i != -1)
  2189.             i = fgetstring(help_handle, str80, 80);
  2190.  
  2191. another_one:
  2192.         i = fgetstring(help_handle, str80, 80);
  2193.         row = 0;
  2194.         textcolor(msg_fg);
  2195.         textbackground(msg_bg);
  2196.         cls();
  2197.  
  2198.         while (strchr(str80, FORMFEED) == NULL && i != -1 && row < 24)
  2199.             {
  2200.             gotoxy(1, ++row);
  2201.             for (j=0; j<strlen(str80); j++)
  2202.                 {
  2203.                 if (str80[j] == 01)
  2204.                     {
  2205.                     textcolor(msg_bg);
  2206.                     textbackground(msg_fg);
  2207.                     }
  2208.                 else
  2209.                 if (str80[j] == 02)
  2210.                     {
  2211.                     textcolor(msg_fg);
  2212.                     textbackground(msg_bg);
  2213.                     }
  2214.                 else
  2215.                     cprintf("%c", str80[j]);
  2216.                 }
  2217.             i = fgetstring(help_handle, str80, 80);
  2218.             }
  2219.  
  2220.         if (i != -1)
  2221.             {
  2222.             message(" ESC to leave Help; any other key to see more Help. ");
  2223.             if (key_char != ESC)
  2224.                 {
  2225.                 i = fgetstring(help_handle, str80, 80);
  2226.                 goto another_one;
  2227.                 }
  2228.             }
  2229.         else
  2230.             message(" ");
  2231.  
  2232.         DosClose(help_handle);
  2233.         term_type = term_type_save;
  2234.         }
  2235.  
  2236.  
  2237. void    scroll_up(void)
  2238.         {
  2239.         _BH = (reg_bg << 4) | reg_fg;
  2240.         _AX = 0x0601;
  2241.         _CX = 0x0000;
  2242.         _DX = 0x184F;
  2243.         geninterrupt(0x10);
  2244.         }
  2245.  
  2246. void    scroll_up_top(void)
  2247.         {
  2248.         _BH = (reg_bg << 4) | reg_fg;
  2249.         _AX = 0x0601;
  2250.         _CX = 0x0000;
  2251.         _DX = 0x0F4F;
  2252.         geninterrupt(0x10);
  2253.         }
  2254.  
  2255. void    scroll_down(void)
  2256.         {
  2257.         _BH = (reg_bg << 4) | reg_fg;
  2258.         _AX = 0x0701;
  2259.         _CX = 0x0000;
  2260.         _DX = 0x184F;
  2261.         geninterrupt(0x10);
  2262.         }
  2263.  
  2264. void    scroll_down_top(void)
  2265.         {
  2266.         _BH = (reg_bg << 4) | reg_fg;
  2267.         _AX = 0x0701;
  2268.         _CX = 0x0000;
  2269.         _DX = 0x0F4F;
  2270.         geninterrupt(0x10);
  2271.         }
  2272.  
  2273. void    scroll_up_bottom(void)
  2274.         {
  2275.         _BH = (msg_bg << 4) | msg_fg;
  2276.         _AX = 0x0601;
  2277.         _CX = 0x1000;
  2278.         _DX = 0x184F;
  2279.         geninterrupt(0x10);
  2280.         }
  2281.  
  2282. void    display_chat_bottom(char ch)
  2283.         {
  2284.         int  x;
  2285.  
  2286.         if (ch == LINEFEED || ch == CTRLS || ch == CTRLQ) return;
  2287.  
  2288.         if (ch == CR)
  2289.             {
  2290.             if (wherey() == 9)
  2291.                 {
  2292.                 if (mouse_exists) hide_mouse();
  2293.                 scroll_up_bottom();
  2294.                 gotoxy(1, 9);
  2295.                 if (mouse_exists) show_mouse();
  2296.                 }
  2297.             else
  2298.                 {
  2299.                 gotoxy(1, bottom_chat_y+1);
  2300.                 }
  2301.             return;
  2302.             }
  2303.  
  2304.         if (mouse_exists) hide_mouse();
  2305.         if (ch == BS)
  2306.             cprintf("%s", bs_str);
  2307.         else
  2308.         if (ch == TAB)
  2309.             {
  2310.             x = wherex();
  2311.             x = 8 - ((x + 7) % 8);
  2312.             cprintf("%*.*s", x, x, " ");
  2313.             }
  2314.         else
  2315.             cprintf("%c", ch);
  2316.         if (mouse_exists) show_mouse();
  2317.         }
  2318.  
  2319.  
  2320. void    display_char(char ch)
  2321.         {
  2322.         int  x;
  2323.         int  last_line;
  2324.  
  2325.         screen_is_clear = FALSE;
  2326.  
  2327.         if (term_type == CHAT)
  2328.             last_line = 16;
  2329.         else
  2330.             last_line = 25;
  2331.  
  2332.         if (wherex() == 80 && ch != LINEFEED && ch != CR && ch != BS)
  2333.             {
  2334.             if (mouse_exists) hide_mouse();
  2335.             cprintf("%c%c", CR, LINEFEED);
  2336.             if (mouse_exists) show_mouse();
  2337.             }
  2338.  
  2339.         if (wherey() == last_line && ch == LINEFEED)
  2340.             {
  2341.             if (mouse_exists) hide_mouse();
  2342.             x = wherex();
  2343.             if (term_type == CHAT)
  2344.                 scroll_up_top();
  2345.             else
  2346.                 scroll_up();
  2347.             gotoxy(x, last_line - 1);
  2348.             if (mouse_exists) show_mouse();
  2349.             }
  2350.  
  2351.         if (mouse_exists) hide_mouse();
  2352.         if (ch == BS)
  2353.             cprintf("%s", bs_str);
  2354.         else
  2355.         if (ch == TAB)
  2356.             {
  2357.             x = wherex();
  2358.             x = 8 - ((x + 7) % 8);
  2359.             cprintf("%*.*s", x, x, " ");
  2360.             }
  2361.         else
  2362.             cprintf("%c", ch);
  2363.         if (mouse_exists) show_mouse();
  2364.  
  2365.         if (term_type == CHAT)
  2366.             {
  2367.             top_chat_x = wherex();
  2368.             top_chat_y = wherey();
  2369.             }
  2370.         }
  2371.  
  2372.  
  2373. void    display_line(int i)
  2374.         {
  2375.         char    *p1, *p2;
  2376.  
  2377.         p1 = line_ptrs[i];
  2378.         if (p1 == NULL) return;
  2379.  
  2380.         if (++i == MAX_LINES) i = 0;
  2381.         p2 = line_ptrs[i];
  2382.         if (p2 == NULL) p2 = &modem_buff[tail];
  2383.  
  2384.         while (p1 != p2 && *p1 != LINEFEED)
  2385.             {
  2386.             display_char(*p1);
  2387.             if (++p1 == &modem_buff[SBUFSIZ]) p1 = &modem_buff[0];
  2388.             }
  2389.         }
  2390.  
  2391.  
  2392. void    do_up_motion(int x, int y)
  2393.         {
  2394.         if (disp_line == 0) return;
  2395.  
  2396.         if (y > 1)
  2397.             {
  2398.             while (y != 1 && disp_line != 0)
  2399.                 {
  2400.                 disp_line--;
  2401.                 y--;
  2402.                 gotoxy(x, y);
  2403.                 }
  2404.             return;
  2405.             }
  2406.  
  2407.         if (term_type == CHAT)
  2408.             scroll_down_top();
  2409.         else
  2410.             scroll_down();
  2411.  
  2412.         gotoxy(1, 1);
  2413.         if (!screen_is_clear)
  2414.             disp_line--;
  2415.  
  2416.         display_line(disp_line);
  2417.         screen_is_clear = FALSE;
  2418.         gotoxy(x, 1);
  2419.         }
  2420.  
  2421. void    do_down_motion(int x, int y)
  2422.         {
  2423.         if (disp_line == curr_line) return;
  2424.         if (screen_is_clear) return;
  2425.  
  2426.         if (y < bottom_line)
  2427.             {
  2428.             while (y != bottom_line && disp_line != curr_line)
  2429.                 {
  2430.                 disp_line++;
  2431.                 y++;
  2432.                 gotoxy(x, y);
  2433.                 }
  2434.             return;
  2435.             }
  2436.  
  2437.         if (term_type == CHAT)
  2438.             scroll_up_top();
  2439.         else
  2440.             scroll_up();
  2441.  
  2442.         gotoxy(1, bottom_line);
  2443.         disp_line++;
  2444.         display_line(disp_line);
  2445.         gotoxy(x, bottom_line);
  2446.         }
  2447.  
  2448.  
  2449. void    show_screenfull(void)
  2450.         {
  2451.         int  y;
  2452.  
  2453.         cls();
  2454.         for (y=1; y<=bottom_line; y++, disp_line++)
  2455.             {
  2456.             gotoxy(1, y);
  2457.             display_line(disp_line);
  2458.             if (disp_line == curr_line) return;
  2459.             }
  2460.         disp_line--;
  2461.         }
  2462.  
  2463. void    scroll_buffer(void)
  2464.         {
  2465.         int   r, x, y;
  2466.  
  2467.         x = wherex();  y = wherey();
  2468.         bottom_line = 25;
  2469.         if (mouse_exists) hide_mouse();
  2470.  
  2471.         if (term_type == CHAT)
  2472.             {
  2473.             window(1, 1, 80, 16);
  2474.             gotoxy(top_chat_x, top_chat_y);
  2475.             x = top_chat_x; 
  2476.             y = top_chat_y;
  2477.             bottom_line = 16;
  2478.             }
  2479.  
  2480. scr_buf_action:
  2481.         if (extended_char == UPKEY)
  2482.             {
  2483.             do_up_motion(x, y);
  2484.             }
  2485.         else
  2486.         if (extended_char == DOWNKEY)
  2487.             {
  2488.             do_down_motion(x, y);
  2489.             }
  2490.         else
  2491.         if (extended_char == HOMEKEY)
  2492.             {
  2493.             disp_line = 0;
  2494.             show_screenfull();
  2495.             }
  2496.         else
  2497.         if (extended_char == ENDKEY)
  2498.             {
  2499.             if (disp_line == curr_line) goto scrbuf_exit;
  2500.             disp_line = max(curr_line-bottom_line+2, 0);
  2501.             show_screenfull();
  2502.             }
  2503.         else
  2504.         if (extended_char == PGUPKEY)
  2505.             {
  2506.             if (disp_line < bottom_line)
  2507.                 {
  2508.                 extended_char = HOMEKEY;
  2509.                 goto scr_buf_action;
  2510.                 }
  2511.             r = disp_line + 2 - (bottom_line + y);
  2512.             disp_line = max(r, 0);
  2513.             show_screenfull();
  2514.             }
  2515.         else
  2516.         if (extended_char == PGDNKEY)
  2517.             {
  2518.             r = disp_line + bottom_line - y;
  2519.             disp_line = min(r, curr_line);
  2520.             if (disp_line > curr_line - bottom_line)
  2521.                 {
  2522.                 extended_char = ENDKEY;
  2523.                 goto scr_buf_action;
  2524.                 }
  2525.             show_screenfull();
  2526.             }
  2527.  
  2528. scrbuf_exit:
  2529.         if (term_type == CHAT)
  2530.             {
  2531.             top_chat_y = wherey();
  2532.             window(1, 1, 80, 25);
  2533.             }
  2534.         if (mouse_exists) show_mouse();
  2535.         }
  2536.  
  2537.  
  2538. void    init_line_pointers(void)
  2539.         {
  2540.         int a;
  2541.  
  2542.         for (a=0; a<MAX_LINES; a++)
  2543.             line_ptrs[a] = NULL;
  2544.         disp_line = curr_line = 0;
  2545.         line_ptrs[0] = &modem_buff[tail];
  2546.         line_sub = 1;
  2547.         }
  2548.  
  2549.  
  2550. int     chk_abort_requested(void)
  2551.         {
  2552.         if (key_char == ESC || break_flag)
  2553.             {
  2554.             break_flag = FALSE;
  2555.             if (mouse_exists) show_mouse();
  2556.             ask_yn("Sure you want to end the transfer?");
  2557.             if (mouse_exists) hide_mouse();
  2558.             textcolor(msg_fg);
  2559.             textbackground(msg_bg);
  2560.             if (key_char == 'y')
  2561.                 {
  2562.                 user_abort = TRUE;
  2563.                 return TRUE;
  2564.                 }
  2565.             }
  2566.         return FALSE;
  2567.         }
  2568.  
  2569.  
  2570. int     get_filename(void)
  2571.         {
  2572.         char    linsav[160];
  2573.         int     cpos, ctype, h;
  2574.  
  2575.         file_bytes = 0l;
  2576.         blocks_to_send = 0;
  2577.         setmem(filename, sizeof(filename)-1, 0);
  2578.  
  2579.         if (mouse_exists) hide_mouse();
  2580.         save_screen(1,25,80,25, linsav, &cpos, &ctype);
  2581.  
  2582.         textcolor(msg_fg);
  2583.         textbackground(msg_bg);
  2584.         gotoxy(1, 25);
  2585.         cprintf("Filename? ");
  2586.         kbdstring(filename, 45);
  2587.  
  2588.         restore_screen(1,25,80,25, linsav, &cpos, &ctype);
  2589.         if (mouse_exists) show_mouse();
  2590.  
  2591.         if (strlen(filename) == 0)
  2592.             return 0;
  2593.  
  2594.         h = DosOpen(filename, 0);
  2595.         if (h == -1)
  2596.             {
  2597.             if (crit_err_occurred)
  2598.                 {
  2599.                 crit_err_occurred = FALSE;
  2600.                 return 0;
  2601.                 }
  2602.             return -1;
  2603.             }
  2604.  
  2605.         file_bytes = filelength(h);
  2606.         if (transfer_type == XMODEM_SEND)
  2607.             blocks_to_send = (unsigned) ((filelength(h) +127l) / 128l);
  2608.         else
  2609.         if (transfer_type == YMODEM_SEND)
  2610.             blocks_to_send = (unsigned) ((filelength(h) +1023l) / 1024l);
  2611.         DosClose(h);
  2612.         return 1;
  2613.         }
  2614.  
  2615. void    init_for_transfer(void)
  2616.         {
  2617.         name_ptrs[0] = NULL;
  2618.         name_ptrs[1] = NULL;
  2619.         critical_error = FALSE;
  2620.  
  2621.         old_parity        = paritysave;
  2622.         old_bits          = bitssave;
  2623.         old_stop          = stop_bitsave;
  2624.         open_port(port_id, speedsave, NO_PAR, 8, 1);
  2625.  
  2626.         timeout_value     = 11l * 18l;
  2627.         timeout_ticks     = tick_counter + timeout_value;
  2628.  
  2629.         x_index           = 0;
  2630.         block_count       = 0;
  2631.         error_count       = 0;
  2632.         errors_this_block = 0;
  2633.         EOF_flag          = FALSE;
  2634.         xfr_abort         = FALSE;
  2635.         user_abort        = FALSE;
  2636.         eot_processed     = FALSE;
  2637.         transferring_file = TRUE;
  2638.         }
  2639.  
  2640. void    title_the_box(void)
  2641.         {
  2642.         gotoxy(20, 8);
  2643.         switch (transfer_type)
  2644.             {
  2645.             case XMODEM_RECV:
  2646.                 cprintf("[XModem Receive]");
  2647.                 break;
  2648.             case YMODEM_RECV:
  2649.                 cprintf("[YModem Receive]");
  2650.                 break;
  2651.             case XMODEM_SEND:
  2652.                 cprintf("[XModem Send]");
  2653.                 break;
  2654.             case YMODEM_SEND:
  2655.                 cprintf("[YModem Send]");
  2656.                 break;
  2657.             case KERMIT_RECV:
  2658.                 cprintf("[Kermit Receive]");
  2659.                 break;
  2660.             case KERMIT_SEND:
  2661.                 cprintf("[Kermit Send]");
  2662.                 break;
  2663.             default : break;
  2664.             }
  2665.         }
  2666.  
  2667. void    draw_transfer_box(void)
  2668.         {
  2669.         if (mouse_exists) hide_mouse();
  2670.  
  2671.         textcolor(msg_fg);
  2672.         textbackground(msg_bg);
  2673.         gotoxy(16, 8);
  2674.         cprintf("%s", xfr_box[0]);
  2675.         for (i=0; i<6; i++)
  2676.             {
  2677.             gotoxy(16, i+9);
  2678.             cprintf("%s", xfr_box[1]);
  2679.             }
  2680.         gotoxy(16, 15);
  2681.         cprintf("%s", xfr_box[2]);
  2682.  
  2683.         title_the_box();
  2684.  
  2685.         gotoxy(17, 9);
  2686.         strupr(filename);
  2687.         cprintf("%-39.39s", filename);
  2688.         gotoxy(18, 15);
  2689.         cprintf("[ESC-Abort   Alt/X-foreground task]");
  2690.  
  2691.         if (transfer_type == XMODEM_SEND 
  2692.           || transfer_type == YMODEM_SEND)
  2693.             {
  2694.             gotoxy(17, 11);
  2695.             cprintf("Total blocks: %5u", blocks_to_send);
  2696.             }
  2697.  
  2698.         gotoxy(17, 12);
  2699.         cprintf(" Good blocks: %5u", block_count);
  2700.         gotoxy(17, 13);
  2701.         cprintf("Error blocks: %5u", error_count);
  2702.         if (mouse_exists) show_mouse();
  2703.         }
  2704.  
  2705. void    fg_transfer_processing(void)
  2706.         {
  2707.         if (mouse_exists) hide_mouse();
  2708.  
  2709.         while (transferring_file)
  2710.             {
  2711.             do_transfer();
  2712.             if (hot_flag)
  2713.                 {
  2714.                 leave_flag = TRUE;
  2715.                 goto fg_tp_exit;
  2716.                 }
  2717.             if (block_count != j || error_count != k)
  2718.                 {
  2719.                 if (transfer_type == XMODEM_SEND 
  2720.                   || transfer_type == YMODEM_SEND)
  2721.                     {
  2722.                     gotoxy(31, 11);
  2723.                     cprintf("%5u", blocks_to_send);
  2724.                     }
  2725.                 gotoxy(31, 12);
  2726.                 cprintf("%5u", block_count);
  2727.                 if (error_count < 0)
  2728.                     error_count = 0;
  2729.                 gotoxy(31, 13);
  2730.                 cprintf("%5u", error_count);
  2731.                 j = block_count;
  2732.                 k = error_count;
  2733.                 }
  2734.             if (bioskey(1) || break_flag)
  2735.                 {
  2736.                 getkey();
  2737.                 if (key_char == 0 && extended_char == ALTX)
  2738.                     {
  2739.                     leave_flag = TRUE;
  2740.                     goto fg_tp_exit;
  2741.                     }
  2742.                 chk_abort_requested();
  2743.                 }
  2744.             }
  2745.  
  2746. fg_tp_exit:
  2747.         if (mouse_exists) show_mouse();
  2748.         textcolor(reg_fg);
  2749.         textbackground(reg_bg);
  2750.         }
  2751.  
  2752.  
  2753. void    show_final_stats(void)
  2754.         {
  2755.         open_port(port_id, speedsave, old_parity, old_bits, old_stop);
  2756.  
  2757.         if (mouse_exists) hide_mouse();
  2758.         textcolor(msg_fg);
  2759.         textbackground(msg_bg);
  2760.         gotoxy(16, 8);
  2761.         cprintf("%s", xfr_box[0]);
  2762.         for (i=0; i<6; i++)
  2763.             {
  2764.             gotoxy(16, i+9);
  2765.             cprintf("%s", xfr_box[1]);
  2766.             }
  2767.         gotoxy(16, 15);
  2768.         cprintf("%s", xfr_box[2]);
  2769.  
  2770.         title_the_box();
  2771.  
  2772.         gotoxy(17, 9);
  2773.         strupr(filename);
  2774.         cprintf("%-39.39s", filename);
  2775.         if (transfer_type == XMODEM_SEND || transfer_type == YMODEM_SEND)
  2776.             {
  2777.             gotoxy(17, 11);
  2778.             cprintf("Total blocks: %5u", blocks_to_send);
  2779.             }
  2780.         gotoxy(17, 12);
  2781.         cprintf(" Good blocks: %5u", block_count);
  2782.         gotoxy(17, 13);
  2783.         cprintf("Error blocks: %5u", error_count);
  2784.         gotoxy(17, 14);
  2785.         if (xfr_abort)
  2786.             cprintf("Transfer aborted.  Press a key.");
  2787.         else
  2788.             cprintf("Transfer complete.  Press a key.");
  2789.  
  2790.         if (mouse_exists) show_mouse();
  2791.         getkey();
  2792.         stats_in_progress = FALSE;
  2793.         transfer_type = NO_TRANSFER;
  2794.         init_line_pointers();
  2795.  
  2796.         textcolor(reg_fg);
  2797.         textbackground(reg_bg);
  2798.         }
  2799.  
  2800. void    receive_xymodem(void)
  2801.         {
  2802.         j = k = 0;
  2803.         if (stats_in_progress) goto show_recv_stats;
  2804.  
  2805. get_name:
  2806.         j = get_filename();
  2807.         if (j == 0) return;
  2808.         if (j == 1)
  2809.             {
  2810.             beep();
  2811.             ask_yn("File exists already.  Replace it?");
  2812.             if (key_char == 'n')
  2813.                 goto get_name;
  2814.             }
  2815.  
  2816.         j = 0;
  2817.         init_for_transfer();
  2818.  
  2819. show_recv_stats:
  2820.         stats_in_progress = TRUE;
  2821.         draw_transfer_box();
  2822.  
  2823.         fg_transfer_processing();
  2824.         if (leave_flag) return;
  2825.  
  2826.         show_final_stats();
  2827.         }
  2828.  
  2829.  
  2830. void    send_xymodem(void)
  2831.         {
  2832.         j = k = 0;
  2833.         if (stats_in_progress) goto show_send_stats;
  2834.  
  2835. get_name:
  2836.         j = get_filename();
  2837.         if (j == 0) return;
  2838.         if (j == -1)
  2839.             {
  2840.             beep();
  2841.             message("File not found.");
  2842.             goto get_name;
  2843.             }
  2844.  
  2845.         j = 0;
  2846.         init_for_transfer();
  2847.  
  2848. show_send_stats:
  2849.         stats_in_progress = TRUE;
  2850.         draw_transfer_box();
  2851.  
  2852.         fg_transfer_processing();
  2853.         if (leave_flag) return;
  2854.  
  2855.         show_final_stats();
  2856.         }
  2857.  
  2858. void    receive_kermit(void)
  2859.         {
  2860.         char    linsav[160];
  2861.         int     cpos, ctype;
  2862.         char    a;
  2863.  
  2864.         j = k = 0;
  2865.         if (stats_in_progress) goto show_recv_stats;
  2866.  
  2867.         save_screen(1,25,80,25, linsav, &cpos, &ctype);
  2868.         setmem(kermit_path, sizeof(kermit_path)-1, 0);
  2869.         textcolor(msg_fg);
  2870.         textbackground(msg_bg);
  2871.  
  2872. get_directory:
  2873.         gotoxy(1, 25);
  2874.         cprintf("Drive:\\Path (─┘ for current) ");
  2875.         kbdstring(kermit_path, 39);
  2876.         if (strlen(kermit_path) != 0)
  2877.             {
  2878.             a = kermit_path[strlen(kermit_path)-1];
  2879.             if (a != '\\' && a != ':')
  2880.                 strcat(kermit_path, "\\");
  2881.             strcpy(string1, kermit_path);
  2882.             strcat(string1, "kertemp.$$$");
  2883.             if ( (j = DosCreate(string1)) == -1)
  2884.                 {
  2885.                 beep();
  2886.                 goto get_directory;
  2887.                 }
  2888.             DosClose(j);
  2889.             unlink(string1);
  2890.             }
  2891.  
  2892.         restore_screen(1,25,80,25, linsav, &cpos, &ctype);
  2893.  
  2894.         init_for_transfer();
  2895.         setmem(filename, sizeof(filename)-1, 0);
  2896.  
  2897. show_recv_stats:
  2898.         stats_in_progress = TRUE;
  2899.         draw_transfer_box();
  2900.         fg_transfer_processing();
  2901.         if (leave_flag) return;
  2902.  
  2903.         show_final_stats();
  2904.         }
  2905.  
  2906. void    send_kermit(void)
  2907.         {
  2908.         int     res, w;
  2909.         struct  ffblk ff;
  2910.  
  2911.         j = k = 0;
  2912.         if (stats_in_progress) goto show_send_stats;
  2913.  
  2914. get_name:
  2915.         if (get_filename() == 0) return;
  2916.  
  2917.         res=findfirst(filename, &ff, 0);
  2918.         if (res != 0 || critical_error)
  2919.             {
  2920.             critical_error = FALSE;
  2921.             goto get_name;
  2922.             }
  2923.  
  2924.         init_for_transfer();
  2925.  
  2926.         _filecount = w = 0;
  2927.         name_area = xmodem_area;
  2928.         _filelist = name_ptrs;
  2929.  
  2930.         while (res == 0 && !critical_error) 
  2931.             {
  2932.             if (_filecount > 24 || w > 1000) break;
  2933.             strcpy(&name_area[w], ff.ff_name);
  2934.             name_ptrs[_filecount] = &name_area[w];
  2935.             w  += strlen(ff.ff_name) + 1;
  2936.             _filecount++;
  2937.             res = findnext(&ff);
  2938.             }
  2939.  
  2940. show_send_stats:
  2941.         stats_in_progress = TRUE;
  2942.         draw_transfer_box();
  2943.  
  2944.         fg_transfer_processing();
  2945.         if (leave_flag) return;
  2946.  
  2947.         show_final_stats();
  2948.         }
  2949.  
  2950. void    receive_ascii(void)
  2951.         {
  2952.         char    linsav[160];
  2953.         int     h;
  2954.         unsigned long j;
  2955.  
  2956.         j = 0l;
  2957.  
  2958.         if (stats_in_progress) goto show_recv_stats;
  2959.  
  2960. get_name:
  2961.         h = get_filename();
  2962.         if (h == 0) return;
  2963.         if (h == 1)
  2964.             {
  2965.             beep();
  2966.             ask_yn("File exists already.  Replace it?");
  2967.             if (key_char == 'n')
  2968.                 goto get_name;
  2969.             }
  2970.  
  2971.         setmem(holdstr, 81, 0);
  2972.         timeout_value     = 11l * 18l;
  2973.         timeout_ticks     = tick_counter + timeout_value;
  2974.         EOF_flag          = FALSE;
  2975.         xfr_abort         = FALSE;
  2976.         user_abort        = FALSE;
  2977.         transferring_file = TRUE;
  2978.         term_type_save    = term_type;
  2979.         term_type         = NORMAL;
  2980.  
  2981. show_recv_stats:
  2982.         stats_in_progress = TRUE;
  2983.  
  2984.         if (mouse_exists) hide_mouse();
  2985.         textcolor(msg_fg);
  2986.         textbackground(msg_bg);
  2987.         gotoxy(1, 16);
  2988.         cprintf("%s", ascii_box[0]);
  2989.         for (i=0; i<7; i++)
  2990.             {
  2991.             gotoxy(1, i+17);
  2992.             cprintf("%s", ascii_box[1]);
  2993.             }
  2994.         gotoxy(1, 24);
  2995.         cprintf("%s", ascii_box[2]);
  2996.         gettext(1, 24, 80, 24, linsav);
  2997.         puttext(1, 25, 80, 25, linsav);
  2998.         gotoxy(1, 24);
  2999.         cprintf("%s", ascii_box[1]);
  3000.  
  3001.         gotoxy(10, 16);
  3002.         cprintf("[ASCII Receive -- %s]", filename);
  3003.         gotoxy(10, 25);
  3004.         cprintf("[ESC when done   Received: %7lu]", byte_count);
  3005.  
  3006.         oldx = oldy = 1;
  3007.  
  3008.         while (transferring_file)
  3009.             {
  3010.             do_transfer();
  3011.             if (hot_flag)
  3012.                 {
  3013.                 leave_flag = TRUE;
  3014.                 if (mouse_exists) show_mouse();
  3015.                 textcolor(reg_fg);
  3016.                 textbackground(reg_bg);
  3017.                 return;
  3018.                 }
  3019.             if (j != byte_count)
  3020.                 {
  3021.                 gotoxy(37, 25);
  3022.                 cprintf("%7lu", byte_count);
  3023.                 j = byte_count;
  3024.                 }
  3025.             if (bioskey(1) || break_flag)
  3026.                 {
  3027.                 getkey();
  3028.                 chk_abort_requested();
  3029.                 if (key_char == 0 && extended_char == ALTX)
  3030.                     {
  3031.                     leave_flag = TRUE;
  3032.                     if (mouse_exists) show_mouse();
  3033.                     textcolor(reg_fg);
  3034.                     textbackground(reg_bg);
  3035.                     return;
  3036.                     }
  3037.                 if (!user_abort && key_char != 0)
  3038.                     {
  3039.                     send_char(key_char);
  3040.                     }
  3041.                 }
  3042.             }
  3043.  
  3044.         gotoxy(10, 25);
  3045.         cprintf("[Transfer complete <press a key>.   Received: %7lu]",
  3046.                         byte_count);
  3047.  
  3048.         if (mouse_exists) show_mouse();
  3049.         getkey();
  3050.         stats_in_progress = FALSE;
  3051.         transfer_type = NO_TRANSFER;
  3052.         did_ascii_xfr = TRUE;
  3053.  
  3054.         textcolor(reg_fg);
  3055.         textbackground(reg_bg);
  3056.         }
  3057.  
  3058.  
  3059. void    send_ascii(void)
  3060.         {
  3061.         char     linsav[160];
  3062.         int      h;
  3063.         unsigned long j;
  3064.  
  3065.         j = 0l;
  3066.  
  3067.         if (stats_in_progress) goto show_send_stats;
  3068.  
  3069. get_name:
  3070.         h = get_filename();
  3071.         if (h == 0) return;
  3072.         if (h == -1)
  3073.             {
  3074.             beep();
  3075.             message("File not found.");
  3076.             goto get_name;
  3077.             }
  3078.  
  3079.         setmem(holdstr, 81, 0);
  3080.         timeout_value     = 11l * 18l;
  3081.         timeout_ticks     = tick_counter + timeout_value;
  3082.         EOF_flag          = FALSE;
  3083.         xfr_abort         = FALSE;
  3084.         user_abort        = FALSE;
  3085.         transferring_file = TRUE;
  3086.         term_type_save    = term_type;
  3087.         term_type         = NORMAL;
  3088.  
  3089. show_send_stats:
  3090.         stats_in_progress = TRUE;
  3091.  
  3092.         if (mouse_exists) hide_mouse();
  3093.         textcolor(msg_fg);
  3094.         textbackground(msg_bg);
  3095.         gotoxy(1, 16);
  3096.         cprintf("%s", ascii_box[0]);
  3097.         for (i=0; i<7; i++)
  3098.             {
  3099.             gotoxy(1, i+17);
  3100.             cprintf("%s", ascii_box[1]);
  3101.             }
  3102.         gotoxy(1, 24);
  3103.         cprintf("%s", ascii_box[2]);
  3104.         gettext(1, 24, 80, 24, linsav);
  3105.         puttext(1, 25, 80, 25, linsav);
  3106.         gotoxy(1, 24);
  3107.         cprintf("%s", ascii_box[1]);
  3108.  
  3109.         gotoxy(10, 16);
  3110.         cprintf("[ASCII Send -- %s]", filename);
  3111.         gotoxy(10, 25);
  3112.         cprintf("[ESC to interrupt  File size: %7lu  Sent: %7lu]", 
  3113.                     file_bytes, byte_count);
  3114.  
  3115.         oldx = oldy = 1;
  3116.  
  3117.         while (transferring_file)
  3118.             {
  3119.             do_transfer();
  3120.             if (hot_flag)
  3121.                 {
  3122.                 leave_flag = TRUE;
  3123.                 if (mouse_exists) show_mouse();
  3124.                 textcolor(reg_fg);
  3125.                 textbackground(reg_bg);
  3126.                 return;
  3127.                 }
  3128.             if (j != byte_count)
  3129.                 {
  3130.                 gotoxy(55, 25);
  3131.                 cprintf("%7lu", byte_count);
  3132.                 j = byte_count;
  3133.                 }
  3134.             if (bioskey(1) || break_flag)
  3135.                 {
  3136.                 getkey();
  3137.                 if (key_char == 0 && extended_char == ALTX)
  3138.                     {
  3139.                     leave_flag = TRUE;
  3140.                     if (mouse_exists) show_mouse();
  3141.                     textcolor(reg_fg);
  3142.                     textbackground(reg_bg);
  3143.                     return;
  3144.                     }
  3145.                 chk_abort_requested();
  3146.                 }
  3147.             }
  3148.  
  3149.         gotoxy(10, 25);
  3150.         cprintf("[Done <press a key>.  File size: %7lu  Sent: %7lu]", 
  3151.                     file_bytes, byte_count);
  3152.  
  3153.         window(2, 17, 79, 24);
  3154.         gotoxy(oldx, oldy);
  3155.         textcolor(msg_fg);
  3156.         textbackground(msg_bg);
  3157.  
  3158.         while ( !bioskey(1) )
  3159.             if ( (i = get_modem()) != -1 )
  3160.                 display_char( (char) i);
  3161.  
  3162.         if (mouse_exists) show_mouse();
  3163.         getkey();
  3164.         oldx = wherex();
  3165.         oldy = wherey();
  3166.         window(1, 1, 80, 25);
  3167.  
  3168.         stats_in_progress = FALSE;
  3169.         transfer_type = NO_TRANSFER;
  3170.         did_ascii_xfr = TRUE;
  3171.  
  3172.         textcolor(reg_fg);
  3173.         textbackground(reg_bg);
  3174.         }
  3175.  
  3176. void    capture_file(void)
  3177.         {
  3178.         int h;
  3179.  
  3180.         if (capturing)
  3181.             {
  3182.             DosClose(capture_handle);
  3183.             capturing = FALSE;
  3184.             transferring_file = FALSE;
  3185.             return;
  3186.             }
  3187.  
  3188. get_name:
  3189.         h = get_filename();
  3190.         if (h == 0) return;
  3191.  
  3192.         strlwr(filename);
  3193.         if ( (filename[0] == 'l' && filename[1] == 'p' && filename[2] == 't')
  3194.              ||
  3195.              (filename[0] == 'p' && filename[1] == 'r' && filename[2] == 'n') )
  3196.                 {
  3197.                 if ( (capture_handle = DosOpen(filename, 2)) == -1)
  3198.                     {
  3199.                     beep();
  3200.                     return;
  3201.                     }
  3202.                 capturing = TRUE;
  3203.                 transferring_file = TRUE;
  3204.                 return;
  3205.                 }
  3206.  
  3207.         if (h == 1)
  3208.             {
  3209.             beep();
  3210.             ask_yn("File exists already.  Append to it?");
  3211.             if (key_char == 'y')
  3212.                 {
  3213.                 if ( (capture_handle = DosOpen(filename, 2)) == -1)
  3214.                     {
  3215.                     beep();
  3216.                     return;
  3217.                     }
  3218.                 DosSeekEOF(capture_handle);
  3219.                 capturing = TRUE;
  3220.                 transferring_file = TRUE;
  3221.                 return;
  3222.                 }
  3223.             ask_yn("Replace it?");
  3224.             if (key_char == 'n')
  3225.                 goto get_name;
  3226.             }
  3227.  
  3228.         if ( (capture_handle = DosCreate(filename)) == -1)
  3229.             {
  3230.             beep();
  3231.             return;
  3232.             }
  3233.  
  3234.         capturing = TRUE;
  3235.         transferring_file = TRUE;
  3236.         }
  3237.  
  3238.  
  3239. void    set_term(int tt)
  3240.         {
  3241.         if (term_type == tt) return;
  3242.  
  3243.         if (tt == CHAT)
  3244.             switch_to_chat = TRUE;
  3245.         else
  3246.         if (term_type == CHAT)
  3247.             switch_from_chat = TRUE;
  3248.  
  3249.         term_type = tt;
  3250.         }
  3251.  
  3252.  
  3253. void    change_port(void)
  3254.         {
  3255.         switch (our_port)
  3256.             {
  3257.             case 1 : {our_port = 2; break;}
  3258.             case 2 : {our_port = 3; break;}
  3259.             case 3 : {our_port = 4; break;}
  3260.             case 4 : {our_port = 1; break;}
  3261.             default: {our_port = 1; break;}
  3262.             }
  3263.         re_open_flag = TRUE;
  3264.         }
  3265.  
  3266. void    change_baud(void)
  3267.         {
  3268.         switch (our_speed)
  3269.             {
  3270.             case 110   : {our_speed =  150; break;}
  3271.             case 150   : {our_speed =  300; break;}
  3272.             case 300   : {our_speed =  600; break;}
  3273.             case 600   : {our_speed = 1200; break;}
  3274.             case 1200  : {our_speed = 2400; break;}
  3275.             case 2400  : {our_speed = 4800; break;}
  3276.             case 4800  : {our_speed = 9600; break;}
  3277.             case 9600  : {our_speed =19200; break;}
  3278.             case 19200 : {our_speed =38400l; break;}
  3279.             case 38400l: {our_speed =  110; break;}
  3280.             default    : {our_speed = 1200; break;}
  3281.             }
  3282.         re_open_flag = TRUE;
  3283.         }
  3284.  
  3285. void    change_data(void)
  3286.         {
  3287.         switch (our_bits)
  3288.             {
  3289.             case 5 : {our_bits = 6; break;}
  3290.             case 6 : {our_bits = 7; break;}
  3291.             case 7 : {our_bits = 8; break;}
  3292.             case 8 : {our_bits = 5; break;}
  3293.             default: {our_bits = 7; break;}
  3294.             }
  3295.         re_open_flag = TRUE;
  3296.         }
  3297.  
  3298. void    change_parity(void)
  3299.         {
  3300.         switch (our_par)
  3301.             {
  3302.             case EV_PAR : {our_par = NO_PAR; break;}
  3303.             case NO_PAR : {our_par = OD_PAR; break;}
  3304.             case OD_PAR : {our_par = EV_PAR; break;}
  3305.             default     : {our_par = EV_PAR; break;}
  3306.             }
  3307.         re_open_flag = TRUE;
  3308.         }
  3309.  
  3310. void    change_stop(void)
  3311.         {
  3312.         our_stop = our_stop == 2? 1 : 2;
  3313.         re_open_flag = TRUE;
  3314.         }
  3315.  
  3316. void    change_echo(void)
  3317.         {
  3318.         echo_flag = echo_flag? FALSE : TRUE;
  3319.         }
  3320.  
  3321. void    change_xon(void)
  3322.         {
  3323.         flow_control = flow_control? FALSE : TRUE;
  3324.         }
  3325.  
  3326. void    change_add_lf(void)
  3327.         {
  3328.         crlf_for_cr = crlf_for_cr? FALSE : TRUE;
  3329.         }
  3330.  
  3331. void    change_auto_answer(void)
  3332.         {
  3333.         if (carrier()) return;
  3334.         auto_answer = auto_answer? FALSE : TRUE;
  3335.  
  3336.         if (auto_answer)
  3337.             send_string(answer_on);
  3338.         else
  3339.             send_string(answer_off);
  3340.         }
  3341.  
  3342.  
  3343.  
  3344. int     parse_phone_entry(int sel)
  3345.         {
  3346.         char    *token;
  3347.  
  3348.         setmem(string1, LINE_LENGTH, 0);
  3349.         strncpy(string1, phone_list[sel], LINE_LENGTH);
  3350.  
  3351.         token = strtok(string1, ";");
  3352.         if (token == NULL) {dial_error = 1; return -1;}
  3353.         if (strncmp(token, "          ", 10) == 0)
  3354.             {dial_error = 1; return -1;}
  3355.  
  3356.         token = strtok(NULL, ";");
  3357.         if (token == NULL) {dial_error = 2; return -1;}
  3358.         if (strlen(token) > 28) {dial_error = 2; return -1;}
  3359.         strcpy(phone_number, token);
  3360.  
  3361.         token = strtok(NULL, ";");
  3362.         if (token == NULL) {dial_error = 3; return -1;}
  3363.         speedsave = (unsigned) atol(token);
  3364.         if ( speedsave < 1
  3365.           || speedsave > MAX_BAUD) {dial_error = 3; return -1;}
  3366.         our_speed = speedsave;
  3367.  
  3368.         token = strtok(NULL, ";");
  3369.         if (token == NULL) {dial_error = 0; return -1;}
  3370.         strcpy(string2, token);
  3371.  
  3372.         token = strtok(NULL, ";");
  3373.         if (token == NULL) {dial_error = 7; return -1;}
  3374.         strcpy(string3, token);
  3375.         strcat(string3, " ");
  3376.         strlwr(string3);
  3377.         if (strstr(string3, "noecho") != NULL)
  3378.             echo_flag = FALSE;
  3379.         else
  3380.         if (strstr(string3, "echo") != NULL)
  3381.             echo_flag = TRUE;
  3382.         else
  3383.             {dial_error = 7; return -1;}
  3384.  
  3385.         token = strtok(NULL, ";");
  3386.         if (token == NULL) {dial_error = 8; return -1;}
  3387.         strcpy(string3, token);
  3388.         strcat(string3, " ");
  3389.         strlwr(string3);
  3390.         if (strstr(string3, "noflow") != NULL)
  3391.             flow_control = FALSE;
  3392.         else
  3393.         if (strstr(string3, "flow") != NULL)
  3394.             flow_control = TRUE;
  3395.         else
  3396.             {dial_error = 8; return -1;}
  3397.  
  3398.         token = strtok(NULL, ";");
  3399.         if (token == NULL) {dial_error = 9; return -1;}
  3400.         strcpy(string3, token);
  3401.         strcat(string3, " ");
  3402.         strlwr(string3);
  3403.         if (strstr(string3, "yes") != NULL)
  3404.             crlf_for_cr = TRUE;
  3405.         else
  3406.         if (strstr(string3, "no") != NULL)
  3407.             crlf_for_cr = FALSE;
  3408.         else
  3409.             {dial_error = 9; return -1;}
  3410.  
  3411.         token = strtok(string2, "-");
  3412.         if (token == NULL) {dial_error = 4; return -1;}
  3413.         if (atoi(token) < 5 || atoi(token) > 8)
  3414.             {dial_error = 4; return -1;}
  3415.         our_bits = atoi(token);
  3416.  
  3417.         token = strtok(NULL, "-");
  3418.         if (token == NULL) {dial_error = 5; return -1;}
  3419.         strcpy(string3, token);
  3420.         strlwr(string3);
  3421.         if (string3[0] == 'e')
  3422.             our_par = EV_PAR;
  3423.         else
  3424.         if (string3[0] == 'o')
  3425.             our_par = OD_PAR;
  3426.         else
  3427.         if (string3[0] == 'n')
  3428.             our_par = NO_PAR;
  3429.         else
  3430.             {dial_error = 5; return -1;}
  3431.  
  3432.         token = strtok(NULL, " -");
  3433.         if (token == NULL) {dial_error = 6; return -1;}
  3434.         if (atoi(token) < 1 || atoi(token) > 2)
  3435.             {dial_error = 6; return -1;}
  3436.         our_stop = atoi(token);
  3437.  
  3438.         return 0;
  3439.         }
  3440.  
  3441.  
  3442. int     make_the_call(void)
  3443.         {
  3444.         int  dialing_period;
  3445.  
  3446.         call_in_progress = FALSE;
  3447.         setmem(holdstr, 81, 0);
  3448.         flag_save = echo_flag;
  3449.         echo_flag = FALSE;
  3450.         send_string(dial_cmd);
  3451.         send_string(phone_number);
  3452.         send_char(CR);
  3453.         echo_flag = flag_save;
  3454.  
  3455.         dialing_period = 1;
  3456.         while (dialing_period <= dial_wait_secs)
  3457.             {
  3458.             if (strlen(no_carrier_msg) > 0
  3459.                 && strstr(holdstr, no_carrier_msg) != NULL)
  3460.                     return 0;
  3461.             if (strlen(phone_busy) > 0
  3462.                 && strstr(holdstr, phone_busy) != NULL)
  3463.                     return 0;
  3464.             if (strlen(connect_msg) > 0)
  3465.                 {
  3466.                 if (strstr(holdstr, connect_msg) != NULL)
  3467.                     {
  3468.                     call_in_progress = TRUE;
  3469.                     return 1;
  3470.                     }
  3471.                 }
  3472.             if (use_carrier && carrier())
  3473.                 {
  3474.                 call_in_progress = TRUE;
  3475.                 return 1;
  3476.                 }
  3477.             else
  3478.             if (!use_carrier)
  3479.                 {
  3480.                 call_in_progress = TRUE;
  3481.                 return 1;
  3482.                 }
  3483.  
  3484.             if (in_popup)
  3485.                 {
  3486.                 gotoxy(1, 25);
  3487.                 textcolor(msg_fg);
  3488.                 textbackground(msg_bg);
  3489.                 cprintf("[%2d secs.]  ", dialing_period);
  3490.                 }
  3491.  
  3492.             purge_buffer();
  3493.             dialing_period++;
  3494.  
  3495.             if ( mouse_exists && right_button_up() ) 
  3496.                 {
  3497.                 if (!carrier())
  3498.                     send_char(CR);
  3499.                 return -1;
  3500.                 }
  3501.  
  3502.             if (bioskey(1))
  3503.                 {
  3504.                 getkey();
  3505.                 if (key_char == ESC)
  3506.                     {
  3507.                     if (!carrier())
  3508.                         send_char(CR);
  3509.                     return -1;
  3510.                     }
  3511.                 }
  3512.             }
  3513.  
  3514.         return 0;
  3515.         }
  3516.  
  3517.  
  3518. void    tell_modem_to_dial(void)
  3519.         {
  3520.         char    linsav[160];
  3521.         int     cpos, ctype;
  3522.         int     r;
  3523.  
  3524.         if (mouse_exists) hide_mouse();
  3525.         save_screen(1,25,80,25, linsav, &cpos, &ctype);
  3526.         textcolor(msg_fg);
  3527.         textbackground(msg_bg);
  3528.         gotoxy(1, 25);
  3529.         cprintf(
  3530.     "             Dialing %-23.23s         (ESC to interrupt)        ",
  3531.             phone_number);
  3532.  
  3533.         r = make_the_call();
  3534.         restore_screen(1,25,80,25, linsav, &cpos, &ctype);
  3535.  
  3536.         textcolor(msg_fg);
  3537.         textbackground(msg_bg);
  3538.         gotoxy(69, 1);
  3539.         if (carrier())
  3540.             cprintf("[Online ]");
  3541.         else
  3542.             cprintf("[Offline]");
  3543.         textcolor(reg_fg);
  3544.         textbackground(reg_bg);
  3545.  
  3546.         if (mouse_exists) show_mouse();
  3547.  
  3548.         if (r == -1)
  3549.             {
  3550.             message("Dialing interrupted. ");
  3551.             goto tmtd_exit;
  3552.             }
  3553.  
  3554.         if (r == 0) 
  3555.             {
  3556.             beep();
  3557.             message(" The call was unsuccessful. ");
  3558.             goto tmtd_exit;
  3559.             }
  3560.  
  3561.         message("  The other computer has answered the phone.  ");
  3562.  
  3563. tmtd_exit:
  3564.         ;
  3565.         }
  3566.  
  3567.  
  3568. void    dial_manually(void)
  3569.         {
  3570.         char    linsav[160];
  3571.         int     cpos, ctype;
  3572.  
  3573.         if (carrier())
  3574.             {
  3575.             beep();
  3576.             return;
  3577.             }
  3578.  
  3579.         if (mouse_exists) hide_mouse();
  3580.         save_screen(1,25,80,25, linsav, &cpos, &ctype);
  3581.         setmem(phone_number, sizeof(phone_number)-1, 0);
  3582.         textcolor(msg_fg);
  3583.         textbackground(msg_bg);
  3584.         gotoxy(1, 25);
  3585.         cprintf("Phone number? ");
  3586.         kbdstring(phone_number, 29);
  3587.         restore_screen(1,25,80,25, linsav, &cpos, &ctype);
  3588.         if (mouse_exists) show_mouse();
  3589.  
  3590.         if (strlen(phone_number) == 0)
  3591.             return;
  3592.  
  3593.         tell_modem_to_dial();
  3594.         }
  3595.  
  3596.  
  3597. void    dial_phone(int sel)
  3598.         {
  3599.         if (carrier())
  3600.             {
  3601.             beep();
  3602.             return;
  3603.             }
  3604.  
  3605.         if (parse_phone_entry(sel) == -1)
  3606.             {
  3607.             beep();
  3608.             sprintf(string1, "%s missing or invalid.", dial_msg[dial_error]);
  3609.             message(string1);
  3610.             return;
  3611.             }
  3612.  
  3613.         close_port();
  3614.         open_port(our_port,our_speed,our_par,our_bits,our_stop);
  3615.  
  3616.         tell_modem_to_dial();
  3617.         }
  3618.  
  3619. /************************************/
  3620.  
  3621. int     hangup_phone(void)
  3622.         {
  3623.         int     retry_cnt;
  3624.         char    linsav[160];
  3625.         int     cpos, ctype;
  3626.  
  3627.         if (!carrier() || strlen(hangup) == 0)
  3628.             {
  3629.             beep();
  3630.             return(-1);
  3631.             }
  3632.  
  3633.         ask_yn("Sure you want to hang up?");
  3634.         if (key_char == 'n')
  3635.             return(-1);
  3636.  
  3637.         if (mouse_exists) hide_mouse();
  3638.         save_screen(1,25,80,25, linsav, &cpos, &ctype);
  3639.         textcolor(msg_fg);
  3640.         textbackground(msg_bg);
  3641.         gotoxy(1, 25);
  3642.         cprintf(
  3643. "  Ok.  Hanging up the phone.           (please wait...)                       ");
  3644.  
  3645.         setmem(holdstr, 81, 0);
  3646.  
  3647.         drop_dtr();
  3648.         if (!carrier())
  3649.             goto hup_exit;
  3650.  
  3651.         flag_save = echo_flag;
  3652.         echo_flag = FALSE;
  3653.         retry_cnt = 0;
  3654.  
  3655. retry:
  3656.         send_string(hangup);
  3657.         delay(100);
  3658.         if (carrier() && retry_cnt < 2)
  3659.             {
  3660.             retry_cnt++;
  3661.             goto retry;
  3662.             }
  3663.         echo_flag = flag_save;
  3664.  
  3665. hup_exit:
  3666.         call_in_progress = FALSE;
  3667.         restore_screen(1,25,80,25, linsav, &cpos, &ctype);
  3668.  
  3669.         textcolor(msg_fg);
  3670.         textbackground(msg_bg);
  3671.         gotoxy(69, 1);
  3672.         if (carrier())
  3673.             cprintf("[Online ]");
  3674.         else
  3675.             cprintf("[Offline]");
  3676.         textcolor(reg_fg);
  3677.         textbackground(reg_bg);
  3678.  
  3679.         if (mouse_exists) show_mouse();
  3680.  
  3681.         return(0);
  3682.         }
  3683.  
  3684.  
  3685.  
  3686. unsigned int     get_color(char *s1)
  3687.         {
  3688.         if (strstr(s1, "darkgray") != NULL)
  3689.             return(DARKGRAY);
  3690.         if (strstr(s1, "lightblue") != NULL)
  3691.             return(LIGHTBLUE);
  3692.         if (strstr(s1, "lightgreen") != NULL)
  3693.             return(LIGHTGREEN);
  3694.         if (strstr(s1, "lightcyan") != NULL)
  3695.             return(LIGHTCYAN);
  3696.         if (strstr(s1, "lightred") != NULL)
  3697.             return(LIGHTRED);
  3698.         if (strstr(s1, "lightmagenta") != NULL)
  3699.             return(LIGHTMAGENTA);
  3700.         if (strstr(s1, "yellow") != NULL)
  3701.             return(YELLOW);
  3702.         if (strstr(s1, "brightwhite") != NULL)
  3703.             return(BRIGHTWHITE);
  3704.         if (strstr(s1, "black") != NULL)
  3705.             return(BLACK);
  3706.         if (strstr(s1, "blue") != NULL)
  3707.             return(BLUE);
  3708.         if (strstr(s1, "green") != NULL)
  3709.             return(GREEN);
  3710.         if (strstr(s1, "cyan") != NULL)
  3711.             return(CYAN);
  3712.         if (strstr(s1, "red") != NULL)
  3713.             return(RED);
  3714.         if (strstr(s1, "magenta") != NULL)
  3715.             return(MAGENTA);
  3716.         if (strstr(s1, "brown") != NULL)
  3717.             return(BROWN);
  3718.         if (strstr(s1, "white") != NULL)
  3719.             return(WHITE);
  3720.         if (strstr(s1, "highintensity") != NULL)
  3721.             return(HIGHINTENSITY);
  3722.         if (strstr(s1, "underline") != NULL)
  3723.             return(UNDERLINE);
  3724.  
  3725.         return(-1);
  3726.         }
  3727.  
  3728. /************************************/
  3729.  
  3730. void    get_parms(void)
  3731.         {
  3732.         int     i1;
  3733.         char    *t1;
  3734.  
  3735.         strtok(string2, "=");
  3736.  
  3737.         i1 = atoi(strtok(NULL, "-/ \n"));
  3738.         if (i1 < 5 || i1 > 8) {config_error = 7; return;}
  3739.         our_bits = i1;
  3740.  
  3741.         t1 = strtok(NULL, "-/ \n");
  3742.         if (strcmp(t1, "e") EQ)
  3743.             our_par = EV_PAR;
  3744.         else
  3745.         if (strcmp(t1, "n") EQ)
  3746.             our_par = NO_PAR;
  3747.         else
  3748.         if (strcmp(t1, "o") EQ)
  3749.             our_par = OD_PAR;
  3750.         else
  3751.             {config_error = 8; return;};
  3752.  
  3753.         i1 = atoi(strtok(NULL, "-/ \n"));
  3754.         if (i1 < 1 || i1 > 2) {config_error = 9; return;}
  3755.         our_stop = i1;
  3756.         }
  3757.  
  3758.  
  3759. void    get_string_token(char *id, char *t, int toklen)
  3760.         {
  3761.         if (strstr(string2, id) != NULL)
  3762.             if (strtok(string1, "=") != NULL)
  3763.                 strncpy(t, strtok(NULL, "\n"), toklen);
  3764.         }
  3765.  
  3766. void    get_int_token(char *id, unsigned int *t)
  3767.         {
  3768.         if (strstr(string2, id) != NULL)
  3769.             if (strtok(string1, "=") != NULL)
  3770.                 *t = (unsigned) atol(strtok(NULL, "\n"));
  3771.         }
  3772.  
  3773. void    get_boolean_token(char *id, unsigned char *t)
  3774.         {
  3775.         char *p;
  3776.  
  3777.         if (strstr(string2, id) != NULL)
  3778.             if (strtok(string2, "=") != NULL)
  3779.                 {
  3780.                 p = strtok(NULL, "\n");
  3781.                 if (strstr(p, "yes") != NULL || strstr(p, "on") != NULL)
  3782.                     *t = TRUE;
  3783.                 else
  3784.                 if (strstr(p, "no") != NULL || strstr(p, "off") != NULL)
  3785.                     *t = FALSE;
  3786.                 }
  3787.         }
  3788.  
  3789. /************************************/
  3790.  
  3791. int     get_config(char *config_name)
  3792.         {
  3793.         char   *p;
  3794.         char   spath[81];
  3795.         int    i1;
  3796.  
  3797.         config_error = -1;
  3798.         strcpy(spath, config_name);
  3799.  
  3800. find_the_file:
  3801.         if ( (p = searchpath(spath)) == NULL || critical_error )
  3802.             {
  3803.             if (strchr(spath, '.') == NULL && !critical_error)
  3804.                 {
  3805.                 strcat(spath, ".CFG");
  3806.                 goto find_the_file;
  3807.                 }
  3808.             critical_error = FALSE;
  3809.             config_error = 0;
  3810.             return(-1);
  3811.             }
  3812.  
  3813.         strcpy(string1, p);
  3814.         handle = DosOpen(string1, 0);
  3815.         if (handle < 1)
  3816.             {
  3817.             config_error = 0;
  3818.             return(-1);
  3819.             }
  3820.  
  3821.         fbufndx   = 2000;
  3822.         fbufbytes = 0;
  3823.  
  3824.         while ((fgetstring(handle, string1, 80)) != -1)
  3825.             {
  3826.             if (string1[0] == ';' || string1[0] == '*')
  3827.                 continue;
  3828.             strcat(string1, "\n");
  3829.             strcpy(string2, string1);
  3830.             strlwr(string2);
  3831.             if (strstr(string2, "phone dir") != NULL)
  3832.                 {
  3833.                 for (i1 = 0; i1 < 10; i1++)
  3834.                     {
  3835.                     strcpy(phone_list[i1], "          ");
  3836.                     strcpy(dial_menu[i1], "                          ");
  3837.                     }
  3838.                 dial_count = 0;
  3839.                 while ((fgetstring(handle, string1, 80)) != -1)
  3840.                     {
  3841.                     if (string1[0] == ';' || string1[0] == '*')
  3842.                         continue;
  3843.                     strcat(string1, ";");
  3844.                     while ( (p = strchr(string1, TAB)) != NULL )
  3845.                         *p = ' ';
  3846.                     strcpy(string2, string1);
  3847.                     strlwr(string2);
  3848.                     if (dial_count > 9)
  3849.                         break;
  3850.                     if (strlen(string1) < 7)
  3851.                         break;
  3852.                     if (strstr(string2, "modem string") != NULL) 
  3853.                         break;
  3854.                     strcpy(phone_list[dial_count], string1);
  3855.                     strtok(string1, ";");
  3856.                     for (i1=strlen(string1); i1<25; i1++)
  3857.                         string1[i1] = ' ';
  3858.                     string1[24] = '\0';
  3859.                     strcpy(dial_menu[dial_count], "  ");
  3860.                     strcat(dial_menu[dial_count], string1);
  3861.                     dial_count++;
  3862.                     }
  3863.                 }
  3864.             else
  3865.             if (strstr(string2, "regular foreground") != NULL)
  3866.                 {
  3867.                 if ((i1 = get_color(string2)) == -1)
  3868.                     config_error = 1;
  3869.                 else
  3870.                     reg_fg = (unsigned char) i1;
  3871.                 }
  3872.             else
  3873.             if (strstr(string2, "regular background") != NULL)
  3874.                 {
  3875.                 if ((i1 = get_color(string2)) == -1)
  3876.                     config_error = 2;
  3877.                 else
  3878.                     reg_bg = (unsigned char) i1;
  3879.                 }
  3880.             else
  3881.             if (strstr(string2, "message foreground") != NULL)
  3882.                 {
  3883.                 if ((i1 = get_color(string2)) == -1)
  3884.                     config_error = 3;
  3885.                 else
  3886.                     msg_fg = (unsigned char) i1;
  3887.                 }
  3888.             else
  3889.             if (strstr(string2, "message background") != NULL)
  3890.                 {
  3891.                 if ((i1 = get_color(string2)) == -1)
  3892.                     config_error = 4;
  3893.                 else
  3894.                     msg_bg = (unsigned char) i1;
  3895.                 }
  3896.             else
  3897.             if (strstr(string2, "parms") != NULL)
  3898.                 get_parms();
  3899.             else
  3900.                 {
  3901.                 get_string_token("phone busy", phone_busy, 20);
  3902.                 get_string_token("no carrier", no_carrier_msg, 20);
  3903.                 get_string_token("dial command", dial_cmd, 20);
  3904.                 get_string_token("modem init", modem_init, 50);
  3905.                 get_string_token("answer on", answer_on, 20);
  3906.                 get_string_token("answer off", answer_off, 20);
  3907.                 get_string_token("modem ok", modem_ok, 20);
  3908.                 get_string_token("modem error", modem_error, 20);
  3909.                 get_string_token("hang", hangup, 50);
  3910.                 get_string_token("connect", connect_msg, 20);
  3911.  
  3912.                 get_int_token("break ms", &break_milliseconds);
  3913.                 get_int_token("foreground ticks", &foreground_ticks);
  3914.                 get_int_token("background ticks", &background_ticks);
  3915.                 get_int_token("xmodem timeout", &xtimeout);
  3916.                 get_int_token("dial wait", &dial_wait_secs);
  3917.                 get_int_token("char send delay", &char_delay);
  3918.                 get_int_token("line send delay", &line_delay);
  3919.                 get_int_token("com port", &our_port);
  3920.                 get_int_token("baud rate", &our_speed);
  3921.  
  3922.                 get_boolean_token("send lf with cr", &send_crlf);
  3923.                 get_boolean_token("use alt", &use_alt);
  3924.                 get_boolean_token("use carrier", &use_carrier);
  3925.                 get_boolean_token("auto answer", &auto_answer);
  3926.                 get_boolean_token("echo", &echo_flag);
  3927.                 get_boolean_token("mouse", &mouse_exists);
  3928.                 }
  3929.  
  3930.             if (strstr(string2, "macro") != NULL)
  3931.                 if (strtok(string1, " ") != NULL)
  3932.                     {
  3933.                     p = strtok(NULL, "=\n");
  3934.                     if (p != NULL)
  3935.                         {
  3936.                         i1 = atoi(p);
  3937.                         if (i1 < 1 || i1 > 9) 
  3938.                             config_error = 17;
  3939.                         else
  3940.                             strncpy(kbd_macro_list[i1-1], strtok(NULL, "\n"), 80);
  3941.                         }
  3942.                     }
  3943.  
  3944.             if (strstr(string2, "auto answer") != NULL)
  3945.                 set_answer  = TRUE;
  3946.             }
  3947.  
  3948.  
  3949.         DosClose(handle);
  3950.  
  3951.         if (our_port < 1 || our_port > 4)
  3952.             config_error = 5;
  3953.         if (our_speed < 1 || our_speed > MAX_BAUD)
  3954.             config_error = 6;
  3955.         if (break_milliseconds < 1 || break_milliseconds > 2000)
  3956.             config_error = 11;
  3957.         if (foreground_ticks < 2 || foreground_ticks > 20)
  3958.             config_error = 12;
  3959.         if (background_ticks < 2 || background_ticks > 20)
  3960.             config_error = 13;
  3961.         if (xtimeout < 1 || xtimeout > 30)
  3962.             config_error = 16;
  3963.         if (dial_wait_secs < 1 || dial_wait_secs > 800)
  3964.            config_error = 14;
  3965.  
  3966.         if (config_error != -1)
  3967.             return(-1);
  3968.  
  3969.         xticks = (long) (xtimeout * 18) + 2;
  3970.  
  3971.         return(0);
  3972.         }
  3973.  
  3974.  
  3975.  
  3976. int     pulldown(int x,        int y, 
  3977.                  int mx1,      int mx2,
  3978.                  int fg,       int bg, 
  3979.                  int count,    int start, 
  3980.                  char *items[])
  3981.         {
  3982.  
  3983.         char *tline = 
  3984. "┬────────────────────────────────────────────────────────────────────────────┬";
  3985.         char *mline = 
  3986. "│                                                                            │";
  3987.         char *bline =
  3988. "└────────────────────────────────────────────────────────────────────────────┘";
  3989.         int     i, len, sx, res;
  3990.         char *menu_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  3991.  
  3992.         len = strlen(items[0]) + 5;
  3993.         sx = x + 3;
  3994.         if (x < mx1) mx1 = x;
  3995.  
  3996.         if (mouse_exists)
  3997.             {
  3998.             left_button_up();
  3999.             right_button_up();
  4000.             }
  4001.  
  4002.         if (dont_redraw)
  4003.             {
  4004.             dont_redraw = FALSE;
  4005.             goto highlight_current;
  4006.             }
  4007.  
  4008.         if (mouse_exists) hide_mouse();
  4009.  
  4010.         textcolor(fg);
  4011.         textbackground(bg);
  4012.         gotoxy(x, y);
  4013.         cprintf("%*.*s", len, len, tline); 
  4014.         cprintf("%c", tline[strlen(tline)-1]);
  4015.         for (i=0; i<count; i++)
  4016.             {
  4017.             gotoxy(x, y+i+1);
  4018.             cprintf("%*.*s", len, len, mline); 
  4019.             cprintf("%c", mline[strlen(mline)-1]);
  4020.             }
  4021.         gotoxy(x, y+count+1);
  4022.         cprintf("%*.*s", len, len, bline); 
  4023.         cprintf("%c", bline[strlen(bline)-1]);
  4024.  
  4025.         textcolor(fg);
  4026.         textbackground(bg);
  4027.         for (i=0; i<count; i++)
  4028.             {
  4029.             gotoxy(sx, y+i+1);
  4030.             cprintf("%s", items[i]);
  4031.             }
  4032.  
  4033.         curr_item = old_item = start;
  4034.         goto highlight_current;
  4035.  
  4036.  
  4037. de_highlight_old:
  4038.         if (mouse_exists) hide_mouse();
  4039.         textcolor(fg);
  4040.         textbackground(bg);
  4041.         gotoxy(sx, y+old_item+1);
  4042.         cprintf("%s", items[old_item]);
  4043.         old_item = curr_item;
  4044.  
  4045. highlight_current:
  4046.         textcolor(bg);
  4047.         textbackground(fg);
  4048.         gotoxy(sx, y+curr_item+1);
  4049.         cprintf("%s", items[curr_item]);
  4050.         if (mouse_exists) show_mouse();
  4051.  
  4052.         if (stats_in_progress)
  4053.             {
  4054.             res = start + 1;
  4055.             goto pulldown_exit;
  4056.             }
  4057.  
  4058. operate_menu:
  4059.         if (mouse_exists)
  4060.             {
  4061.             if ( right_button_up() )
  4062.                 {
  4063.                 res = 0;
  4064.                 goto pulldown_exit;
  4065.                 }
  4066.             if ( left_button_down() )
  4067.                 {
  4068.                 if (left_button_y <= y)
  4069.                     {
  4070.                     if (left_button_x < mx1
  4071.                         || left_button_x > mx2)
  4072.                         {
  4073.                         mouse_menu_x = left_button_x;
  4074.                         return -4;
  4075.                         }
  4076.                     goto operate_menu;
  4077.                     }
  4078.                 if (left_button_y > y + count) goto operate_menu;
  4079.                 if (left_button_x < mx1
  4080.                     || left_button_x > x + len + 1)
  4081.                         {
  4082.                         mouse_menu_x = left_button_x;
  4083.                         return -4;
  4084.                         }
  4085.                 if (curr_item == (left_button_y - y) - 1) goto operate_menu;
  4086.                 curr_item = (left_button_y - y) - 1;
  4087.                 while (strncmp(items[curr_item], "          ", 10) == 0)
  4088.                     {
  4089.                     if (old_item < curr_item)
  4090.                         {
  4091.                         curr_item++;
  4092.                         move_mouse(left_button_x, ++left_button_y);
  4093.                         }
  4094.                     else
  4095.                         {
  4096.                         curr_item--;
  4097.                         move_mouse(left_button_x, --left_button_y);
  4098.                         }
  4099.                     }
  4100.                 goto de_highlight_old;
  4101.                 }
  4102.             if ( left_button_up() )
  4103.                 {
  4104.                 if (left_button_y <= y)
  4105.                     {
  4106.                     if (left_button_x >= mx1 && left_button_x < x + len)
  4107.                         goto operate_menu;
  4108.                     mouse_menu_x = left_button_x;
  4109.                     return -4;
  4110.                     }
  4111.                 if (left_button_x <= mx1
  4112.                     || left_button_x >= x + len - 1
  4113.                     || left_button_y > y + count)
  4114.                         goto operate_menu;
  4115.                 if (left_button_y == y + curr_item + 1)
  4116.                     {
  4117.                     res = curr_item + 1;
  4118.                     goto pulldown_exit;
  4119.                     }
  4120.                 curr_item = (left_button_y - y) - 1;
  4121.                 goto de_highlight_old;
  4122.                 }
  4123.             }
  4124.  
  4125.         if (!bioskey(1)) goto operate_menu;
  4126.  
  4127.         getkey();
  4128.  
  4129. move_lightbar:
  4130.         if (key_char == 0)
  4131.             switch (extended_char)
  4132.                 {
  4133.                 case ALTX    : {res = -3; goto pulldown_exit;}
  4134.                 case LEFTKEY : {res = -2; goto pulldown_exit;}
  4135.                 case RIGHTKEY: {res = -1; goto pulldown_exit;}
  4136.                 case ALTD    : {
  4137.                                res = -4;
  4138.                                mouse_menu_x = 10;
  4139.                                goto pulldown_exit;
  4140.                                }
  4141.                 case ALTS    : {
  4142.                                res = -4;
  4143.                                mouse_menu_x = 25;
  4144.                                goto pulldown_exit;
  4145.                                }
  4146.                 case ALTF    : {
  4147.                                res = -4;
  4148.                                mouse_menu_x = 25;
  4149.                                goto pulldown_exit;
  4150.                                }
  4151.                 case ALTT    : {
  4152.                                res = -4;
  4153.                                mouse_menu_x = 35;
  4154.                                goto pulldown_exit;
  4155.                                }
  4156.                 case ALTM    : {
  4157.                                res = -4;
  4158.                                mouse_menu_x = 50;
  4159.                                goto pulldown_exit;
  4160.                                }
  4161.                 case ALTE    : {
  4162.                                res = -4;
  4163.                                mouse_menu_x = 60;
  4164.                                goto pulldown_exit;
  4165.                                }
  4166.                 case ALTH    : {
  4167.                                res = -4;
  4168.                                mouse_menu_x = 75;
  4169.                                goto pulldown_exit;
  4170.                                }
  4171.                 case UPKEY   : {
  4172.                                if (curr_item == 0)
  4173.                                    curr_item = count - 1;
  4174.                                else
  4175.                                    --curr_item;
  4176.                                if (strncmp(items[curr_item], "          ", 10)
  4177.                                                  == 0)
  4178.                                     goto move_lightbar;
  4179.                                goto de_highlight_old;
  4180.                                }
  4181.                 case DOWNKEY : {
  4182.                                if (curr_item == count - 1)
  4183.                                    curr_item = 0;
  4184.                                else
  4185.                                    ++curr_item;
  4186.                                if (strncmp(items[curr_item], "          ", 10)
  4187.                                                  == 0)
  4188.                                     goto move_lightbar;
  4189.                                goto de_highlight_old;
  4190.                                }
  4191.                 case HOMEKEY : {
  4192.                                curr_item = 0;
  4193.                                goto de_highlight_old;
  4194.                                }
  4195.                 case ENDKEY  : {
  4196.                                curr_item = count - 1;
  4197.                                goto de_highlight_old;
  4198.                                }
  4199.                 case BACKTAB : {
  4200.                                if (curr_item == 0)
  4201.                                    curr_item = count - 1;
  4202.                                else
  4203.                                    --curr_item;
  4204.                                if (strncmp(items[curr_item], "          ", 10)
  4205.                                                  == 0)
  4206.                                     goto move_lightbar;
  4207.                                goto de_highlight_old;
  4208.                                }
  4209.                 default : {
  4210.                           goto operate_menu;
  4211.                           }
  4212.                 }
  4213.  
  4214.         /* not an extended code; handle regular keypress */
  4215.  
  4216.         if (key_char >= 'A' && key_char <= 'z')
  4217.             {
  4218.             key_char = toupper(key_char);
  4219.             i = curr_item;
  4220.             do  {
  4221.                 i = i == count - 1? 0 : i + 1;
  4222.                 if (*strpbrk(items[i], menu_chars) == key_char)
  4223.                     {
  4224.                     curr_item = i;
  4225.                     goto de_highlight_old;
  4226.                     }
  4227.                 }
  4228.                 while (i != curr_item);
  4229.             goto operate_menu;
  4230.             }
  4231.  
  4232.         if (key_char == ESC)            /* ESC  */
  4233.             {
  4234.             res = 0;
  4235.             goto pulldown_exit;
  4236.             }
  4237.  
  4238.         if (key_char == CR)             /* <return> */
  4239.             {
  4240.             res = curr_item + 1;
  4241.             goto pulldown_exit;
  4242.             }
  4243.  
  4244.         if (key_char == ' ')            /* space bar */
  4245.             {
  4246.             if (curr_item == count - 1)
  4247.                 curr_item = 0;
  4248.             else
  4249.                 ++curr_item;
  4250.             if (strncmp(items[curr_item], "          ", 10) == 0)
  4251.                 goto move_lightbar;
  4252.             goto de_highlight_old;
  4253.             }
  4254.  
  4255.         if (key_char == TAB)            /* tab key */
  4256.             {
  4257.             if (curr_item == count - 1)
  4258.                 curr_item = 0;
  4259.             else
  4260.                 ++curr_item;
  4261.             if (strncmp(items[curr_item], "          ", 10) == 0)
  4262.                 goto move_lightbar;
  4263.             goto de_highlight_old;
  4264.             }
  4265.  
  4266.         goto operate_menu;
  4267.  
  4268. pulldown_exit:
  4269.         if (mouse_exists)
  4270.             {
  4271.             left_button_up();
  4272.             right_button_up();
  4273.             }
  4274.         return res;
  4275.         }
  4276.  
  4277. void    put_parms_in_menu(void)
  4278.         {
  4279.         char   s[10];
  4280.  
  4281.         sprintf(&modem_menu[0] [17], "%1d", our_port);
  4282.         sprintf(&modem_menu[1] [13], "%5u", our_speed);
  4283.         sprintf(&modem_menu[2] [17], "%1d", our_bits);
  4284.         if (our_par == EV_PAR) strcpy(s, "EVEN");
  4285.         else if (our_par == OD_PAR) strcpy(s, "ODD ");
  4286.         else strcpy(s, "NONE");
  4287.         sprintf(&modem_menu[3] [14], "%4.4s", s);
  4288.         sprintf(&modem_menu[4] [17], "%1d", our_stop);
  4289.         if (echo_flag) strcpy(s, "ON "); else strcpy(s, "OFF");
  4290.         sprintf(&modem_menu[5] [15], "%3.3s", s);
  4291.         if (flow_control) strcpy(s, "ON "); else strcpy(s, "OFF");
  4292.         sprintf(&modem_menu[6] [15], "%3.3s", s);
  4293.         if (crlf_for_cr) strcpy(s, "ON "); else strcpy(s, "OFF");
  4294.         sprintf(&modem_menu[7] [15], "%3.3s", s);
  4295.         if (auto_answer) strcpy(s, "ON "); else strcpy(s, "OFF");
  4296.         sprintf(&modem_menu[8] [15], "%3.3s", s);
  4297.  
  4298.         if (capturing) strcpy(s, "ON "); else strcpy(s, "OFF");
  4299.         sprintf(&file_menu[8] [15], "%3.3s", s);
  4300.         }
  4301.  
  4302. int     main_menu(int menu_id)
  4303.         {
  4304.         int  r, sx1, sx2, sy1, sy2, cnt, cpos, ctyp, mx1, mx2;
  4305.         char **plist;
  4306.  
  4307.         if (mouse_exists) hide_mouse();
  4308.         save_screen(1, 1, 80, 3, &our_screen[0], &cpos, &ctyp);
  4309.  
  4310.         if (menu_id < 1) menu_id = 1;
  4311.  
  4312.         textcolor(msg_fg);
  4313.         textbackground(msg_bg);
  4314.         gotoxy(1, 1);
  4315.         cprintf(
  4316. "┌──────────────────────────────────────────────────────────────────────────────┐");
  4317.         gotoxy(1, 2);
  4318.         cprintf(
  4319. "│                                                                              │");
  4320.         gotoxy(1, 3);
  4321.         cprintf(
  4322. "└──────────────────────────────────────────────────────────────────────────────┘");
  4323.  
  4324.         gotoxy(5, 1);
  4325.         cprintf("%s", compliments);
  4326.  
  4327.         gotoxy(69, 1);
  4328.         if (carrier())
  4329.             cprintf("[Online ]");
  4330.         else
  4331.             cprintf("[Offline]");
  4332.  
  4333.         if (mouse_exists) show_mouse();
  4334.  
  4335. step4:
  4336.         if (mouse_exists) hide_mouse();
  4337.  
  4338.         textcolor(msg_fg);
  4339.         textbackground(msg_bg);
  4340.         gotoxy(1, 2);
  4341.         cprintf(
  4342. "│ Dialing     File           Terminal    Modem Control    Exit      Help       │");
  4343. /* 3           15             30          42               59        69      */
  4344.  
  4345.         switch (menu_id)
  4346.             {
  4347.             case 1 :{sx1=2; sx2=34; sy1=3; sy2=18; 
  4348.                     mx1=0; mx2=13;
  4349.                     cnt=13; plist=dial_menu;
  4350.                     gotoxy(2, 2);
  4351.                     textcolor(msg_bg);
  4352.                     textbackground(msg_fg);
  4353.                     cprintf(" Dialing ");
  4354.                     break;
  4355.                     }
  4356.             case 2 :{sx1=14; sx2=65; sy1=3; sy2=18; 
  4357.                     mx1=13; mx2=28;
  4358.                     cnt=9; plist=file_menu;
  4359.                     gotoxy(14, 2);
  4360.                     textcolor(msg_bg);
  4361.                     textbackground(msg_fg);
  4362.                     cprintf(" File ");
  4363.                     break;
  4364.                     }
  4365.             case 3 :{sx1=29; sx2=61; sy1=3; sy2=18; 
  4366.                     mx1=28; mx2=40;
  4367.                     cnt= 2; plist=term_menu;
  4368.                     gotoxy(29, 2);
  4369.                     textcolor(msg_bg);
  4370.                     textbackground(msg_fg);
  4371.                     cprintf(" Terminal ");
  4372.                     break;
  4373.                     }
  4374.             case 4 :{sx1=41; sx2=73; sy1=3; sy2=18; 
  4375.                     mx1=40; mx2=57;
  4376.                     cnt= 9; plist=modem_menu;
  4377.                     gotoxy(41, 2);
  4378.                     textcolor(msg_bg);
  4379.                     textbackground(msg_fg);
  4380.                     cprintf(" Modem Control ");
  4381.                     break;
  4382.                     }
  4383.             case 5 :{sx1=58; sx2=79; sy1=3; sy2=18; 
  4384.                     mx1=57; mx2=67;
  4385.                     cnt= 2; plist=exit_menu;
  4386.                     gotoxy(58, 2);
  4387.                     textcolor(msg_bg);
  4388.                     textbackground(msg_fg);
  4389.                     cprintf(" Exit ");
  4390.                     break;
  4391.                     }
  4392.  
  4393.             case 6 :{sx1=59; sx2=79; sy1=3; sy2=18; 
  4394.                     mx1=67; mx2=80;
  4395.                     cnt= 7; plist=help_menu;
  4396.                     gotoxy(68, 2);
  4397.                     textcolor(msg_bg);
  4398.                     textbackground(msg_fg);
  4399.                     cprintf(" Help ");
  4400.                     break;
  4401.                     }
  4402.             }
  4403.  
  4404.         textcolor(msg_fg);
  4405.         textbackground(msg_bg);
  4406.  
  4407.         put_parms_in_menu();
  4408.  
  4409.         gettext(sx1, sy1, sx2, sy2, &our_screen[500]);
  4410.         if (mouse_exists) show_mouse();
  4411.  
  4412. do_pulldown:
  4413.         r = pulldown(sx1, sy1, 
  4414.                      mx1, mx2,
  4415.                      msg_fg, msg_bg, 
  4416.                      cnt, item_recall[menu_id-1], 
  4417.                      plist);
  4418.  
  4419.         item_recall[menu_id-1] = curr_item;
  4420.  
  4421.         if (r < 1)
  4422.             {
  4423.             if (mouse_exists) hide_mouse();
  4424.             puttext(sx1, sy1, sx2, sy2, &our_screen[500]);
  4425.             if (mouse_exists) show_mouse();
  4426.             }
  4427.  
  4428.         if (r == 0 || r == -3)  /*  ESC; ALTX  */
  4429.             goto step99;
  4430.  
  4431.         if (r == -4)    /* mouse menu selection */
  4432.             {
  4433.             if (mouse_menu_x < 13) menu_id = 1;
  4434.             else
  4435.             if (mouse_menu_x < 28) menu_id = 2;
  4436.             else
  4437.             if (mouse_menu_x < 40) menu_id = 3;
  4438.             else
  4439.             if (mouse_menu_x < 57) menu_id = 4;
  4440.             else
  4441.             if (mouse_menu_x < 67) menu_id = 5;
  4442.             else
  4443.                 menu_id = 6;
  4444.             goto step4;
  4445.             }
  4446.  
  4447.         if (r == -1)    /* RIGHT */
  4448.             {
  4449.             if (++menu_id == 7)
  4450.                 menu_id = 1;
  4451.             goto step4;
  4452.             }
  4453.  
  4454.         if (r == -2)    /* LEFT */
  4455.             {
  4456.             if (--menu_id == 0)
  4457.                 menu_id = 6;
  4458.             goto step4;
  4459.             }
  4460.  
  4461.         if (menu_id == 1)
  4462.             {
  4463.             if (r < 11)
  4464.                 {
  4465.                 dial_phone(r-1);
  4466.                 if (!carrier())
  4467.                     goto do_pulldown;
  4468.                 }
  4469.             else
  4470.             if (r == 11)
  4471.                 {
  4472.                 dial_manually();
  4473.                 if (!carrier())
  4474.                     goto do_pulldown;
  4475.                 }
  4476.             else
  4477.             if (r == 13)
  4478.                 {
  4479.                 hangup_phone();
  4480.                 goto do_pulldown;
  4481.                 }
  4482.             else
  4483.             if (r == 12)
  4484.                 {
  4485.                 if (get_filename() != 0)
  4486.                     {
  4487.                     if (get_config(filename) != 0)
  4488.                         {
  4489.                         beep();
  4490.                         sprintf(string1, "Error with '%s': %s.",
  4491.                             filename,
  4492.                             config_msg[config_error]);
  4493.                         message(string1);
  4494.                         }
  4495.                     else
  4496.                         {
  4497.                         message("Phone Directory file loaded.");
  4498.                         }
  4499.                     goto do_pulldown;
  4500.                     }
  4501.                 }
  4502.             if (mouse_exists) hide_mouse();
  4503.             puttext(sx1, sy1, sx2, sy2, &our_screen[500]);
  4504.             if (mouse_exists) show_mouse();
  4505.             goto step99;
  4506.             }
  4507.         else
  4508.         if (menu_id == 2)
  4509.             {
  4510.             if (r == 1)
  4511.                 {
  4512.                 if (!stats_in_progress)
  4513.                     {
  4514.                     transfer_type = XMODEM_RECV;
  4515.                     transfer_init = TRUE;
  4516.                     soh_char = SOH;
  4517.                     nak_char = NAK;
  4518.                     xfr_size = 132;
  4519.                     }
  4520.                 receive_xymodem();
  4521.                 }
  4522.             else
  4523.             if (r == 2)
  4524.                 {
  4525.                 if (!stats_in_progress)
  4526.                     {
  4527.                     transfer_type = YMODEM_RECV;
  4528.                     transfer_init = TRUE;
  4529.                     soh_char = STX;
  4530.                     nak_char = 'C';
  4531.                     xfr_size = 1029;
  4532.                     }
  4533.                 receive_xymodem();
  4534.                 }
  4535.             else
  4536.             if (r == 3)
  4537.                 {
  4538.                 if (!stats_in_progress)
  4539.                     {
  4540.                     transfer_type = KERMIT_RECV;
  4541.                     transfer_init = TRUE;
  4542.                     _eol = CR;              /* EOL for outgoing packets */
  4543.                     _quote = '#';           /* Standard control-quote char "#" */
  4544.                     _pad = 0;               /* No padding */
  4545.                     _padchar = 0;           /* Use null if any padding wanted */
  4546.                     _image = TRUE;          /* Default to no processing for */
  4547.                     _filnamcnv = FALSE;     /* non-UNIX systems */
  4548.                     _escchr = ESCCHR;       /* Default escape character */
  4549.                     }
  4550.                 receive_kermit();
  4551.                 }
  4552.             else
  4553.             if (r == 4)
  4554.                 {
  4555.                 if (!stats_in_progress)
  4556.                     {
  4557.                     transfer_type = ASCII_RECV;
  4558.                     transfer_init = TRUE;
  4559.                     byte_count    = 0;
  4560.                     }
  4561.                 receive_ascii();
  4562.                 }
  4563.             else
  4564.             if (r == 5)
  4565.                 {
  4566.                 if (!stats_in_progress)
  4567.                     {
  4568.                     transfer_type = XMODEM_SEND;
  4569.                     transfer_init = TRUE;
  4570.                     soh_char = SOH;
  4571.                     nak_char = NAK;
  4572.                     xfr_size = 132;
  4573.                     }
  4574.                 send_xymodem();
  4575.                 }
  4576.             else
  4577.             if (r == 6)
  4578.                 {
  4579.                 if (!stats_in_progress)
  4580.                     {
  4581.                     transfer_type = YMODEM_SEND;
  4582.                     transfer_init = TRUE;
  4583.                     soh_char = STX;
  4584.                     nak_char = 'C';
  4585.                     xfr_size = 1029;
  4586.                     }
  4587.                 send_xymodem();
  4588.                 }
  4589.             else
  4590.             if (r == 7)
  4591.                 {
  4592.                 if (!stats_in_progress)
  4593.                     {
  4594.                     transfer_type = KERMIT_SEND;
  4595.                     transfer_init = TRUE;
  4596.                     _eol = CR;              /* EOL for outgoing packets */
  4597.                     _quote = '#';           /* Standard control-quote char "#" */
  4598.                     _pad = 0;               /* No padding */
  4599.                     _padchar = 0;           /* Use null if any padding wanted */
  4600.                     _image = TRUE;          /* Default to no processing for */
  4601.                     _filnamcnv = FALSE;     /* non-UNIX systems */
  4602.                     _escchr = ESCCHR;       /* Default escape character */
  4603.                     }
  4604.                 send_kermit();
  4605.                 }
  4606.             else
  4607.             if (r == 8)
  4608.                 {
  4609.                 if (!stats_in_progress)
  4610.                     {
  4611.                     transfer_type = ASCII_SEND;
  4612.                     transfer_init = TRUE;
  4613.                     byte_count    = 0;
  4614.                     }
  4615.                 send_ascii();
  4616.                 }
  4617.             else
  4618.             if (r == 9)
  4619.                 {
  4620.                 capture_file();
  4621.                 }
  4622.             if (mouse_exists) hide_mouse();
  4623.             puttext(sx1, sy1, sx2, sy2, &our_screen[500]);
  4624.             if (mouse_exists) show_mouse();
  4625.             goto step99;
  4626.             }
  4627.         else
  4628.         if (menu_id == 3)
  4629.             {
  4630.             set_term(r);
  4631.             if (mouse_exists) hide_mouse();
  4632.             puttext(sx1, sy1, sx2, sy2, &our_screen[500]);
  4633.             if (mouse_exists) show_mouse();
  4634.             goto step99;
  4635.             }
  4636.         else
  4637.         if (menu_id == 4)
  4638.             {
  4639.             switch (r)
  4640.                 {
  4641.                 case 1 : {change_port();        break;}
  4642.                 case 2 : {change_baud();        break;}
  4643.                 case 3 : {change_data();        break;}
  4644.                 case 4 : {change_parity();      break;}
  4645.                 case 5 : {change_stop();        break;}
  4646.                 case 6 : {change_echo();        break;}
  4647.                 case 7 : {change_xon();         break;}
  4648.                 case 8 : {change_add_lf();      break;}
  4649.                 case 9 : {
  4650.                          gotoxy(44, 12);
  4651.                          textcolor(msg_bg);
  4652.                          textbackground(msg_fg);
  4653.                          cprintf(" (please wait...) ");
  4654.                          textcolor(reg_bg);
  4655.                          textbackground(reg_fg);
  4656.                          change_auto_answer(); 
  4657.                          break;
  4658.                          }
  4659.                 }
  4660.             put_parms_in_menu();
  4661.             if (re_open_flag)
  4662.                 {
  4663.                 re_open_flag = FALSE;
  4664.                 close_port();
  4665.                 i = open_port(our_port,our_speed,our_par,our_bits,our_stop);
  4666.                 }
  4667.             dont_redraw = TRUE;
  4668.             goto do_pulldown;
  4669.             }
  4670.         else
  4671.         if (menu_id == 5)
  4672.             {
  4673.             leave_flag = TRUE;
  4674.             if (r == 2)
  4675.                 {
  4676.                 de_install = TRUE;
  4677.                 if (!okay_to_unload())
  4678.                     message(
  4679.             "Okay; will do it when offline & other programs gone.");
  4680.                 }
  4681.             if (mouse_exists) hide_mouse();
  4682.             puttext(sx1, sy1, sx2, sy2, &our_screen[500]);
  4683.             if (mouse_exists) show_mouse();
  4684.             goto step99;
  4685.             }
  4686.         else
  4687.         if (menu_id == 6)
  4688.             {
  4689.             if (mouse_exists) hide_mouse();
  4690.             puttext(sx1, sy1, sx2, sy2, &our_screen[500]);
  4691.             restore_screen(1, 1, 80, 3, &our_screen[0], &cpos, &ctyp);
  4692.             save_screen(1, 1, 80, 25, our_screen, &cpos, &ctyp);
  4693.             show_help(r);
  4694.             restore_screen(1, 1, 80, 25, our_screen, &cpos, &ctyp);
  4695.             if (mouse_exists) show_mouse();
  4696.             textcolor(reg_fg);
  4697.             textbackground(reg_bg);
  4698.             return r;
  4699.             }
  4700.  
  4701.         if (mouse_exists) hide_mouse();
  4702.         puttext(sx1, sy1, sx2, sy2, &our_screen[500]);
  4703.         if (mouse_exists) show_mouse();
  4704.         goto step4;
  4705.  
  4706.  
  4707. step99:
  4708.         sticky_menu = menu_id;
  4709.         if (mouse_exists) hide_mouse();
  4710.  
  4711.         if (first_menu_appearance)
  4712.             {
  4713.             first_menu_appearance = FALSE;
  4714.             restore_screen(1, 1, 80, 3, &our_screen[0], &cpos, &ctyp);
  4715.             textcolor(msg_fg);
  4716.             textbackground(msg_bg);
  4717.             gotoxy(1, 1);
  4718.             cprintf(
  4719. "     REMINDER:  Alt-X to Exit.  F2 for Menu.  F1 for Help.                      ");
  4720.             gotoxy(1, 2);
  4721.             if (mouse_exists)
  4722.                 {
  4723.                 cprintf(
  4724. "               Left Button for Menu.  Right Button to Exit.                     ");
  4725.                 gotoxy(1, 3);
  4726.                 }
  4727.             cprintf(
  4728. "                        (Press ─┘ to continue)                                 ");
  4729.             textcolor(reg_fg);
  4730.             textbackground(reg_bg);
  4731.             gotoxy(1, 1);
  4732.             getkey();
  4733.             }
  4734.  
  4735.         restore_screen(1, 1, 80, 3, &our_screen[0], &cpos, &ctyp);
  4736.         if (mouse_exists) show_mouse();
  4737.  
  4738.         if (did_ascii_xfr)
  4739.             {
  4740.             did_ascii_xfr = FALSE;
  4741.             term_type = term_type_save;
  4742.             if (term_type == CHAT)
  4743.                 cls_bottom();
  4744.             cls();
  4745.             top_chat_x = top_chat_y = 1;
  4746.             disp_line = curr_line;
  4747.             extended_char = PGUPKEY;
  4748.             scroll_buffer();
  4749.             extended_char = ENDKEY;
  4750.             scroll_buffer();
  4751.             }
  4752.  
  4753.         if (switch_to_chat)
  4754.             {
  4755.             switch_to_chat = FALSE;
  4756.             cls();
  4757.             top_chat_x = top_chat_y = 1;
  4758.             disp_line = curr_line;
  4759.             cls_bottom();
  4760.             }
  4761.  
  4762.         if (switch_from_chat)
  4763.             {
  4764.             switch_from_chat = FALSE;
  4765.             window(1, 1, 80, 25);
  4766.             textcolor(reg_fg);
  4767.             textbackground(reg_bg);
  4768.             cls();
  4769.             top_chat_x = top_chat_y = 1;
  4770.             disp_line = curr_line;
  4771.             }
  4772.  
  4773.         if (mouse_exists) hide_mouse();
  4774.         save_screen(1, 1, 80, 25, our_screen, &cpos, &ctyp);
  4775.         if (mouse_exists) show_mouse();
  4776.  
  4777.         textcolor(reg_fg);
  4778.         textbackground(reg_bg);
  4779.  
  4780.         alt_menu = FALSE;
  4781.         return r;
  4782.         }
  4783.  
  4784.  
  4785. void    actual_popup(void)
  4786.         {
  4787.         de_install = FALSE;
  4788.         hot_flag   = FALSE;
  4789.         leave_flag = FALSE;
  4790.  
  4791.         textcolor(reg_fg);
  4792.         textbackground(reg_bg);
  4793.  
  4794.         if (first_time)
  4795.             {
  4796.             first_time = FALSE;
  4797.             cls();
  4798.             gotoxy(1, 1);
  4799.             save_screen(1,1,80,25, our_screen, 
  4800.                         &our_cursor_save, &our_cursor_type);
  4801.             }
  4802.  
  4803.         if (!carrier() && set_answer)
  4804.             {
  4805.             set_answer = FALSE;
  4806.             gotoxy(1, 25);
  4807.             textcolor(msg_fg);
  4808.             textbackground(msg_bg);
  4809.             cprintf("Setting auto-answer (please wait)...");
  4810.             if (auto_answer)
  4811.                 send_string(answer_on);
  4812.             else
  4813.                 send_string(answer_off);
  4814.             textcolor(reg_fg);
  4815.             textbackground(reg_bg);
  4816.             }
  4817.  
  4818.         restore_screen(1,1,80,25, our_screen, 
  4819.                            &our_cursor_save, &our_cursor_type);
  4820.  
  4821.         if (mouse_exists && !mouse_shared)
  4822.             show_mouse();
  4823.  
  4824.         if (mouse_exists)
  4825.             {
  4826.             move_mouse(mouse_x_save, mouse_y_save);
  4827.             }
  4828.  
  4829.         if (stats_in_progress)
  4830.             {
  4831.             main_menu(2);
  4832.             if (leave_flag)
  4833.                goto exit_popup;
  4834.             }
  4835.         else
  4836.         if (capturing)
  4837.             {
  4838.             cls();
  4839.             top_chat_x = top_chat_y = 1;
  4840.             disp_line = curr_line;
  4841.             extended_char = PGUPKEY;
  4842.             scroll_buffer();
  4843.             extended_char = ENDKEY;
  4844.             scroll_buffer();
  4845.             }
  4846.  
  4847.         if (!carrier())
  4848.             {
  4849.             main_menu(1);
  4850.             if (leave_flag)
  4851.                goto exit_popup;
  4852.             }
  4853.  
  4854. each_char:
  4855.         if (term_type == CHAT)
  4856.             {
  4857.             if (curr_line == disp_line)
  4858.                 gotoxy(bottom_chat_x, bottom_chat_y+16);
  4859.             else
  4860.                 gotoxy(top_chat_x, top_chat_y);
  4861.             }
  4862.  
  4863.         if (hot_flag)
  4864.             goto exit_popup;
  4865.  
  4866.         if (break_flag)
  4867.             {
  4868.             getkey();
  4869.             textcolor(msg_fg);
  4870.             textbackground(msg_bg);
  4871.             cprintf("*BREAK*");
  4872.             send_break();
  4873.             textcolor(reg_fg);
  4874.             textbackground(reg_bg);
  4875.             }
  4876.  
  4877.         if (mouse_exists)
  4878.             {
  4879.             if (left_button_up())
  4880.                 {
  4881.                 if (carrier())
  4882.                     main_menu(sticky_menu);
  4883.                 else
  4884.                     main_menu(1);
  4885.                 }
  4886.             else
  4887.             if (right_button_up())
  4888.                 {
  4889.                 goto exit_popup;
  4890.                 }
  4891.             }
  4892.  
  4893.         if (alt_menu)
  4894.             {
  4895.             alt_menu = FALSE;
  4896.             if (carrier())
  4897.                 main_menu(sticky_menu);
  4898.             else
  4899.                 main_menu(1);
  4900.             }
  4901.  
  4902.  
  4903.         if (bioskey(1))
  4904.             {
  4905.             getkey();
  4906.             if (key_char != 0)
  4907.                 {
  4908.                 send_char(key_char);
  4909.                 if (term_type == CHAT)
  4910.                     {
  4911.                     window(1, 17, 80, 25);
  4912.                     textcolor(msg_fg);
  4913.                     textbackground(msg_bg);
  4914.                     gotoxy(bottom_chat_x, bottom_chat_y);
  4915.                     display_chat_bottom(key_char);
  4916.                     bottom_chat_x = wherex();
  4917.                     bottom_chat_y = wherey();
  4918.                     textcolor(reg_fg);
  4919.                     textbackground(reg_bg);
  4920.                     window(1, 1, 80, 25);
  4921.                     }
  4922.                 }
  4923.             else
  4924.             if (extended_char == ALTC)
  4925.                 {
  4926.                 cls();
  4927.                 top_chat_x = top_chat_y = 1;
  4928.                 disp_line = curr_line;
  4929.                 }
  4930.             else
  4931.             if (extended_char == ALTX)
  4932.                 goto exit_popup;
  4933.             else
  4934.             if (extended_char == ALTH || extended_char == F1)
  4935.                 main_menu(6);
  4936.             else
  4937.             if (extended_char == F2)
  4938.                 {
  4939.                 if (!carrier()) sticky_menu = 1;
  4940.                 main_menu(sticky_menu);
  4941.                 }
  4942.             else
  4943.             if (extended_char == ALTD || extended_char == F3)
  4944.                 main_menu(1);
  4945.             else
  4946.             if (extended_char == ALTF || extended_char == F4)
  4947.                 main_menu(2);
  4948.             else
  4949.             if (extended_char == ALTT || extended_char == F5)
  4950.                 main_menu(3);
  4951.             else
  4952.             if (extended_char == ALTM || extended_char == F6)
  4953.                 main_menu(4);
  4954.             else
  4955.             if (extended_char == ALTE || extended_char == F7)
  4956.                 main_menu(5);
  4957.             else
  4958.             if (extended_char >= ALT1 && extended_char <= ALT9)
  4959.                 {
  4960.                 i = (int) extended_char;
  4961.                 i -= ALT1;
  4962.                 if (strlen(kbd_macro_list[i]) > 0)
  4963.                     send_string(kbd_macro_list[i]);
  4964.                 }
  4965.             else
  4966.             if ( extended_char == UPKEY
  4967.               || extended_char == DOWNKEY
  4968.               || extended_char == PGUPKEY
  4969.               || extended_char == PGDNKEY
  4970.               || extended_char == HOMEKEY
  4971.               || extended_char == ENDKEY)
  4972.                     scroll_buffer();
  4973.             }
  4974.  
  4975.         if (leave_flag)
  4976.             goto exit_popup;
  4977.  
  4978. read_from_modem:
  4979.         if (disp_line != curr_line)
  4980.             goto each_char;
  4981.  
  4982.         if ((c = get_modem()) != -1)
  4983.             {
  4984.             if (term_type == CHAT)
  4985.                 {
  4986.                 window(1, 1, 80, 16);
  4987.                 gotoxy(top_chat_x, top_chat_y);
  4988.                 bottom_line = 16;
  4989.                 }
  4990.             display_char((char) c);
  4991.             if (term_type == CHAT)
  4992.                 {
  4993.                 if (top_chat_x == 80)
  4994.                     {
  4995.                     display_char(CR);
  4996.                     display_char(LINEFEED);
  4997.                     }
  4998.                 window(1, 1, 80, 25);
  4999.                 }
  5000.             }
  5001.  
  5002.         goto each_char;
  5003.  
  5004.  
  5005. exit_popup:
  5006.         hot_flag   = FALSE;
  5007.         leave_flag = FALSE;
  5008.  
  5009.         if (mouse_exists)
  5010.             {
  5011.             get_mouse();
  5012.             mouse_x_save = mouse_column;
  5013.             mouse_y_save = mouse_row;
  5014.             if (!mouse_shared)
  5015.                 hide_mouse();
  5016.             }
  5017.  
  5018.         if (transferring_file)
  5019.             {
  5020.             if (capturing)
  5021.                 DosClose(dup(capture_handle));
  5022.             if (transfer_type != NO_TRANSFER)
  5023.                 DosClose(dup(transfer_handle));
  5024.             }
  5025.  
  5026.         save_screen(1,1,80,25, our_screen, 
  5027.                         &our_cursor_save, &our_cursor_type);
  5028.         }
  5029.  
  5030.  
  5031. int     get_vid_mode(void)
  5032.         {
  5033.         _AH = 15;
  5034.         geninterrupt(0x10);
  5035.         _AH = 0;
  5036.         temp1 = _AX;
  5037.         return temp1;
  5038.         }
  5039.  
  5040. void    abort_transfer(void)
  5041.         {
  5042.         xfr_abort = TRUE;
  5043.         transferring_file = FALSE;
  5044.         beep();
  5045.         delay(100);
  5046.         beep();
  5047.         DosClose(transfer_handle);
  5048.         send_char(CTRLX); 
  5049.         send_char(CTRLX);
  5050.         purge_buffer();
  5051.         if (transfer_type == XMODEM_RECV || transfer_type == YMODEM_RECV)
  5052.             unlink(filename);
  5053.         }
  5054.  
  5055. void    process_xymodem_char(void)
  5056.         {
  5057.         char    this_block, prev_block;
  5058.         int     i;
  5059.  
  5060.         if (x_index == 0 && xc == EOT)
  5061.             {
  5062.             eot_processed = TRUE;
  5063.             DosClose(transfer_handle);
  5064.             send_char(ACK);
  5065.             transferring_file = FALSE;
  5066.             beep();
  5067.             return;
  5068.             }
  5069.  
  5070.         if (x_index == 0)
  5071.             {
  5072.             timeout_value = xticks;
  5073.             crc = 0;
  5074.             if (xc == SOH)
  5075.                 xfr_size = 132;
  5076.             else
  5077.             if (xc == STX)
  5078.                 xfr_size = 1029;
  5079.             else
  5080.                 return;
  5081.             }
  5082.  
  5083.         xmodem_area[x_index++] = (char) xc;
  5084.  
  5085.         nak_char       = NAK;
  5086.  
  5087.         if (xmodem_area[0] == STX && x_index > 3)
  5088.             crc = updcrc(crc, xc);
  5089.  
  5090.         if (x_index < xfr_size)
  5091.             return;
  5092.  
  5093.         x_index         = 0;
  5094.  
  5095.         this_block = (char) (int) (block_count + 1) % 256;
  5096.         prev_block = (char) (int) (block_count)     % 256;
  5097.  
  5098.         if (   xmodem_area[1] != this_block
  5099.             && xmodem_area[1] != prev_block)
  5100.                goto error_in_block;
  5101.  
  5102.         if (xmodem_area[1] == prev_block)
  5103.             {
  5104.             send_char(ACK);
  5105.             return;
  5106.             }
  5107.  
  5108.         if (xmodem_area[0] == SOH)
  5109.             {
  5110.             chksum = 0;
  5111.             for (i=3; i<131; i++)
  5112.                 chksum+= xmodem_area[i];
  5113.             if (chksum != xmodem_area[131])
  5114.                 goto error_in_block;
  5115.             }
  5116.         else
  5117.             {
  5118.             if (crc != 0)
  5119.                 goto error_in_block;
  5120.             }
  5121.  
  5122.         send_char(ACK);
  5123.         errors_this_block = 0;
  5124.  
  5125.         if (xmodem_area[0] == SOH)
  5126.             io_len = DosWrite(transfer_handle, &xmodem_area[3], 128);
  5127.         else
  5128.             io_len = DosWrite(transfer_handle, &xmodem_area[3], 1024);
  5129.  
  5130.         if (io_len == -1)
  5131.             {
  5132.             errors_this_block = 10;
  5133.             goto error_in_block;
  5134.             }
  5135.  
  5136.         block_count++;
  5137.         return;
  5138.  
  5139.  
  5140. error_in_block:
  5141.         error_count++;
  5142.  
  5143.         if (++errors_this_block >= 10)
  5144.             abort_transfer();
  5145.         else
  5146.             {
  5147.             purge_buffer();
  5148.             send_char(NAK);
  5149.             }
  5150.         }
  5151.  
  5152. /************************************/
  5153.  
  5154. void    build_xmodem_blk(void)
  5155.         {
  5156.         int     blksize;
  5157.  
  5158.         if (transfer_type == XMODEM_SEND)
  5159.             blksize = 128;
  5160.         else
  5161.             blksize = 1024;
  5162.  
  5163.         setmem(xmodem_area, xfr_size, 0);
  5164.         io_len = DosRead(transfer_handle, &xmodem_area[3], blksize);
  5165.         if (io_len == -1)
  5166.             {
  5167.             DosClose(transfer_handle);
  5168.             return;
  5169.             }
  5170.  
  5171.         if (io_len == 0)
  5172.             {
  5173.             DosClose(transfer_handle);
  5174.             xmodem_area[0] = EOT;
  5175.             xfr_size       = 1;
  5176.             EOF_flag       = TRUE;
  5177.             return;
  5178.             }
  5179.  
  5180.         if (transfer_type == XMODEM_SEND)
  5181.             xmodem_area[0] = SOH;
  5182.         else
  5183.             xmodem_area[0] = STX;
  5184.  
  5185.         xmodem_area[1] =  ( (unsigned char) ( (block_count+1) % 256 ) );
  5186.         xmodem_area[2] = ~( (unsigned char) ( (block_count+1) % 256 ) );
  5187.  
  5188.         if (transfer_type == YMODEM_SEND)
  5189.             {
  5190.             crc = 0;
  5191.                for (i=3; i<1027; i++)
  5192.                crc = updcrc(crc, xmodem_area[i]);
  5193.                crc = updcrc(crc, '\0');
  5194.                crc = updcrc(crc, '\0');
  5195.             _DX = crc;
  5196.             xmodem_area[1027] = _DH;
  5197.             xmodem_area[1028] = _DL;
  5198.             }
  5199.         else
  5200.             {
  5201.             chksum = 0;
  5202.             for (i=3; i<131; i++)
  5203.                 chksum+= xmodem_area[i];
  5204.             xmodem_area[131] = chksum;
  5205.             }
  5206.         }
  5207.  
  5208.  
  5209. void    background_xy_recv(void)
  5210.         {
  5211.         if (transfer_init)
  5212.             {
  5213.             transfer_init = FALSE;
  5214.             transfer_handle = DosCreate(filename);
  5215.             if (transfer_handle == -1)
  5216.                 {
  5217.                 transferring_file = FALSE;
  5218.                 xfr_abort = TRUE;
  5219.                 return;
  5220.                 }
  5221.             purge_buffer();
  5222.             send_char(nak_char);
  5223.             }
  5224.  
  5225.         if (user_abort)
  5226.             {
  5227.             abort_transfer();
  5228.             return;
  5229.             }
  5230.  
  5231.         if ((xc = get_modem()) != -1)
  5232.             {
  5233.             process_xymodem_char();
  5234.             timeout_ticks = tick_counter + timeout_value;
  5235.             }
  5236.         else
  5237.         if (tick_counter > timeout_ticks)
  5238.             {
  5239.             error_count++;
  5240.             timeout_ticks = tick_counter + timeout_value;
  5241.             if (++errors_this_block >= 10)
  5242.                 abort_transfer();
  5243.             else
  5244.                 send_char(nak_char);
  5245.             }
  5246.         }
  5247.  
  5248.  
  5249. void    background_xy_send(void)
  5250.         {
  5251.         if (transfer_init)
  5252.             {
  5253.             transfer_init = FALSE;
  5254.             transfer_handle = DosOpen(filename, 0);
  5255.             if (transfer_handle == -1)
  5256.                 {
  5257.                 transferring_file = FALSE;
  5258.                 xfr_abort = TRUE;
  5259.                 return;
  5260.                 }
  5261.             waiting_for_1st_nak = TRUE;
  5262.             return;
  5263.             }
  5264.  
  5265.         if (user_abort)
  5266.             {
  5267.             abort_transfer();
  5268.             return;
  5269.             }
  5270.  
  5271.         if (!output_queue_empty)
  5272.             {
  5273.             timeout_ticks = tick_counter + timeout_value;
  5274.             next_fg_slice = tick_counter;
  5275.             return;
  5276.             }
  5277.  
  5278.         if ((xc = get_modem()) == -1)
  5279.             {
  5280.             if (tick_counter > timeout_ticks)
  5281.                 {
  5282.                 error_count++;
  5283.                 timeout_ticks = tick_counter + timeout_value;
  5284.                 if (++errors_this_block >= 10)
  5285.                     abort_transfer();
  5286.                 }
  5287.             return;
  5288.             }
  5289.  
  5290.         ch = (char) xc;
  5291.  
  5292.         if (waiting_for_1st_nak)
  5293.             {
  5294.             timeout_value = xticks;
  5295.             if (ch == NAK)
  5296.                 {
  5297.                 transfer_type = XMODEM_SEND;
  5298.                 xfr_size = 132;
  5299.                 nak_char = NAK;
  5300.                 soh_char = SOH;
  5301.                 }
  5302.             else
  5303.             if (ch == 'C')
  5304.                 {
  5305.                 transfer_type = YMODEM_SEND;
  5306.                 xfr_size = 1029;
  5307.                 nak_char = 'C';
  5308.                 soh_char = STX;
  5309.                 }
  5310.             }
  5311.  
  5312.         if (ch == ACK)
  5313.             {
  5314.             if (EOF_flag)
  5315.                 {
  5316.                 eot_processed     = TRUE;
  5317.                 transferring_file = FALSE;
  5318.                 beep();
  5319.                 }
  5320.             else
  5321.                 {
  5322.                 block_count++;
  5323.                 errors_this_block   = 0;
  5324.                 prev_char           = 0;
  5325.                 build_xmodem_blk();
  5326.                 for (x_index=0; x_index<xfr_size; x_index++)
  5327.                     send_char(xmodem_area[x_index]);
  5328.                 timeout_ticks = tick_counter + timeout_value;
  5329.                 }
  5330.             return;
  5331.             }
  5332.  
  5333.         if (ch == nak_char)
  5334.             {
  5335.             prev_char = 0;
  5336.             if (!waiting_for_1st_nak)
  5337.                 {
  5338.                 error_count++;
  5339.                 purge_buffer();
  5340.                 if ((++errors_this_block) >= 10)
  5341.                     {
  5342.                     abort_transfer();
  5343.                     return;
  5344.                     }
  5345.                 }
  5346.             else
  5347.                 {
  5348.                 waiting_for_1st_nak = FALSE;
  5349.                 nak_char            = NAK;
  5350.                 purge_buffer();
  5351.                 build_xmodem_blk();
  5352.                 }
  5353.             for (x_index=0; x_index<xfr_size; x_index++)
  5354.                 send_char(xmodem_area[x_index]);
  5355.             timeout_ticks = tick_counter + timeout_value;
  5356.             return;
  5357.             }
  5358.  
  5359.         if (ch == CTRLX && prev_char == CTRLX)
  5360.             {
  5361.             abort_transfer();
  5362.             return;
  5363.             }
  5364.  
  5365.         prev_char = ch;
  5366.         }
  5367.  
  5368.  
  5369. void    write_tty(buffer, nbytes)
  5370.         char *buffer;
  5371.         int  nbytes;
  5372.         {
  5373.         int  i;
  5374.  
  5375.         for (i=0; i<nbytes; i++)
  5376.             {
  5377.             send_char(*buffer);
  5378.             buffer++;
  5379.             }
  5380.         }
  5381.  
  5382.  
  5383. /*
  5384.  *  s e n d s w
  5385.  *
  5386.  *  Sendsw is the state table switcher for sending files.
  5387.  *
  5388.  */
  5389.  
  5390. void    sendsw(void)
  5391.         {
  5392.         switch(_state)
  5393.             {
  5394.             case 'S':   _state = sinit();  return;          /* Send-Init */
  5395.             case 'F':   _state = sfile();  return;          /* Send-File */
  5396.             case 'D':   _state = sdata();  return;          /* Send-Data */
  5397.             case 'Z':   _state = seof();   return;          /* Send-End-of-File */
  5398.             case 'B':   _state = sbreak(); return;          /* Send-Break */
  5399.             case 'C':   transferring_file=FALSE;            /* Complete */
  5400.                         beep();
  5401.                         return;
  5402.             case 'A':   transferring_file=FALSE;            /* "Abort" */
  5403.                         beep();
  5404.                         xfr_abort = TRUE;
  5405.                         return;
  5406.             default:    transferring_file=FALSE;            /* Unknown, fail */
  5407.                         beep();
  5408.                         xfr_abort = TRUE;
  5409.                         return;
  5410.             }
  5411.         }
  5412.  
  5413.  
  5414.  
  5415. /*
  5416.  *  s i n i t
  5417.  *
  5418.  *  Send Initiate: send this host's parameters and get other side's back.
  5419.  */
  5420.  
  5421. char sinit()
  5422. {
  5423. static    int num;                            /* Packet number */
  5424. static    int len;                            /* length */
  5425.  
  5426.     if (!rpack_done) goto rpack_continue;
  5427.  
  5428.     num = len = 0;
  5429.     if (error_count++ > MAXTRY) return('A'); /* If too many tries, give up */
  5430.     spar(_packet);                       /* Fill up init info packet */
  5431.  
  5432.     purge_buffer();                     /* Flush pending input */
  5433.  
  5434.     spack((char)'S',_packnum,10,_packet);        /* Send an S packet */
  5435.  
  5436. rpack_continue:
  5437.     switch(rpack(&len,&num,_recpkt))     /* What was the reply? */
  5438.     {
  5439.         case 'I':  return(_state);       /* Incomplete */
  5440.  
  5441.         case 'N':  return(_state);       /* NAK, try it again */
  5442.  
  5443.         case 'Y':                       /* ACK */
  5444.             if (_packnum != num)         /* If wrong ACK, stay in S state */
  5445.                 return(_state);          /* and try again */
  5446.             rpar(_recpkt);               /* Get other side's init info */
  5447.  
  5448.             if (_eol == 0) _eol = '\n';   /* Check and set defaults */
  5449.             if (_quote == 0) _quote = '#';
  5450.  
  5451.             error_count = 0;                 /* Reset try counter */
  5452.             _packnum = (_packnum+1)%64;   /* Bump packet count */
  5453.             block_count++;
  5454.             return('F');                /* OK, switch state to F */
  5455.  
  5456.         case 'E':                       /* Error packet received */
  5457.             return('A');                /* abort */
  5458.  
  5459.         case FALSE: return(_state);      /* Receive failure, try again */
  5460.  
  5461.         default: return('A');           /* Anything else, just "abort" */
  5462.    }
  5463.  }
  5464.  
  5465.  
  5466. /*
  5467.  *  s f i l e
  5468.  *
  5469.  *  Send File Header.
  5470.  */
  5471.  
  5472. char sfile()
  5473. {
  5474. static    int num;                            /* Packet number */
  5475. static    int len;                            /* length */
  5476. static    char *new_filnam;                   /* Pointer to file name to send */
  5477. static    char *cp;                           /* char pointer */
  5478.  
  5479.     if (!rpack_done) goto rpack_continue;
  5480.  
  5481.     num = len = 0;
  5482.     if (error_count++ > MAXTRY) return('A'); /* If too many tries, give up */
  5483.  
  5484.     transfer_handle = DosOpen(filename, 0);  /* open the file to be sent */
  5485.     if (transfer_handle == -1)
  5486.         {
  5487.         spack((char)'E',_packnum,15,"file open error");  /* Send error packet */
  5488.         return('A');
  5489.         }
  5490.  
  5491.     new_filnam = cp = filename;
  5492.     while (*cp != '\0')                 /* Strip off all leading directory */
  5493.         if (*cp++ == '\\')              /* names (ie. up to the last /). */
  5494.             new_filnam = cp;
  5495.  
  5496.     len = cp - new_filnam;               /* Compute length of new filename */
  5497.     spack((char)'F',_packnum,len,new_filnam);   /* Send an F packet */
  5498.  
  5499. rpack_continue:
  5500.     switch(rpack(&len,&num,_recpkt))     /* What was the reply? */
  5501.     {
  5502.         case 'I':  return(_state);       /* Incomplete */
  5503.  
  5504.         case 'N':                       /* NAK, just stay in this state, */
  5505.             num = (--num<0 ? 63:num);   /* unless it's NAK for next packet */
  5506.             if (_packnum != num)         /* which is just like an ACK for */
  5507.                 return(_state);          /* this packet so fall thru to... */
  5508.  
  5509.         case 'Y':                       /* ACK */
  5510.             if (_packnum != num) return(_state); /* If wrong ACK, stay in F state */
  5511.             error_count = 0;                 /* Reset try counter */
  5512.             _packnum = (_packnum+1)%64;   /* Bump packet count */
  5513.             block_count++;
  5514.             if ((_sizedata = bufill(_packet)) == -1) /* Get data from file */
  5515.                 {
  5516.                 if (io_len == -1) return('A');
  5517.                 return('Z');            /* If EOF set state to that */
  5518.                 }
  5519.             return('D');                /* Switch state to D */
  5520.  
  5521.         case 'E':                       /* Error packet received */
  5522.             return('A');                /* abort */
  5523.  
  5524.         case FALSE: return(_state);      /* Receive failure, stay in F state */
  5525.  
  5526.         default:    return('A');        /* Something else, just "abort" */
  5527.     }
  5528. }
  5529.  
  5530. /*
  5531.  *  s d a t a
  5532.  *
  5533.  *  Send File Data
  5534.  */
  5535.  
  5536. char sdata()
  5537. {
  5538. static    int num;                            /* Packet number */
  5539. static    int len;                            /* length */
  5540.  
  5541.     if (!rpack_done) goto rpack_continue;
  5542.  
  5543.     num = len = 0;
  5544.     if (error_count++ > MAXTRY) return('A'); /* If too many tries, give up */
  5545.  
  5546.     spack((char)'D',_packnum,_sizedata,_packet);     /* Send a D packet */
  5547.  
  5548. rpack_continue:
  5549.     switch(rpack(&len,&num,_recpkt))     /* What was the reply? */
  5550.     {
  5551.         case 'I':  return(_state);       /* Incomplete */
  5552.  
  5553.         case 'N':                       /* NAK, just stay in this state, */
  5554.             num = (--num<0 ? 63:num);   /* unless it's NAK for next packet */
  5555.             if (_packnum != num)         /* which is just like an ACK for */
  5556.                 return(_state);          /* this packet so fall thru to... */
  5557.  
  5558.         case 'Y':                       /* ACK */
  5559.             if (_packnum != num) return(_state); /* If wrong ACK, fail */
  5560.             error_count = 0;                 /* Reset try counter */
  5561.             _packnum = (_packnum+1)%64;   /* Bump packet count */
  5562.             block_count++;
  5563.             if ((_sizedata = bufill(_packet)) == -1) /* Get data from file */
  5564.                 {
  5565.                 if (io_len == -1) return('A');
  5566.                 return('Z');            /* If EOF set state to that */
  5567.                 }
  5568.             return('D');                /* Got data, stay in state D */
  5569.  
  5570.         case 'E':                       /* Error packet received */
  5571.             return('A');                /* abort */
  5572.  
  5573.         case FALSE: return(_state);      /* Receive failure, stay in D */
  5574.  
  5575.         default:    return('A');        /* Anything else, "abort" */
  5576.     }
  5577. }
  5578.  
  5579.  
  5580. /*
  5581.  *  s e o f
  5582.  *
  5583.  *  Send End-Of-File.
  5584.  */
  5585.  
  5586. char seof()
  5587. {
  5588. static    int num;                            /* Packet number */
  5589. static    int len;                            /* length */
  5590.  
  5591.     if (!rpack_done) goto rpack_continue;
  5592.  
  5593.     num = len = 0;
  5594.     if (error_count++ > MAXTRY) return('A'); /* If too many tries, "abort" */
  5595.  
  5596.     spack((char)'Z',_packnum,0,_packet);        /* Send a 'Z' packet */
  5597.  
  5598. rpack_continue:
  5599.     switch(rpack(&len,&num,_recpkt))     /* What was the reply? */
  5600.     {
  5601.         case 'I':  return(_state);       /* Incomplete */
  5602.  
  5603.         case 'N':                       /* NAK, just stay in this state, */
  5604.             num = (--num<0 ? 63:num);   /* unless it's NAK for next packet, */
  5605.             if (_packnum != num)         /* which is just like an ACK for */
  5606.                 return(_state);          /* this packet so fall thru to... */
  5607.  
  5608.         case 'Y':                       /* ACK */
  5609.             if (_packnum != num) return(_state); /* If wrong ACK, hold out */
  5610.             error_count = 0;                 /* Reset try counter */
  5611.             _packnum = (_packnum+1)%64;   /* and bump packet count */
  5612.             block_count++;
  5613.             DosClose(transfer_handle);        /* Close the input file */
  5614.             if (gnxtfl() == FALSE)      /* No more files go? */
  5615.                 return('B');            /* if not, break, EOT, all done */
  5616.             return('F');                /* More files, switch state to F */
  5617.  
  5618.         case 'E':                       /* Error packet received */
  5619.             return('A');                /* abort */
  5620.  
  5621.         case FALSE: return(_state);      /* Receive failure, stay in Z */
  5622.  
  5623.         default:    return('A');        /* Something else, "abort" */
  5624.     }
  5625. }
  5626.  
  5627.  
  5628. /*
  5629.  *  s b r e a k
  5630.  *
  5631.  *  Send Break (EOT)
  5632.  */
  5633.  
  5634. char sbreak()
  5635. {
  5636. static    int num;                            /* Packet number */
  5637. static    int len;                            /* length */
  5638.  
  5639.     if (!rpack_done) goto rpack_continue;
  5640.  
  5641.     num = len = 0;
  5642.     if (error_count++ > MAXTRY) return('A'); /* If too many tries "abort" */
  5643.  
  5644.     spack((char)'B',_packnum,0,_packet);        /* Send a B packet */
  5645.  
  5646. rpack_continue:
  5647.     switch (rpack(&len,&num,_recpkt))    /* What was the reply? */
  5648.     {
  5649.         case 'I':  return(_state);       /* Incomplete */
  5650.  
  5651.         case 'N':                       /* NAK, just stay in this state, */
  5652.             num = (--num<0 ? 63:num);   /* unless NAK for previous packet, */
  5653.             if (_packnum != num)         /* which is just like an ACK for */
  5654.                 return(_state);          /* this packet so fall thru to... */
  5655.  
  5656.         case 'Y':                       /* ACK */
  5657.             if (_packnum != num) return(_state); /* If wrong ACK, fail */
  5658.             error_count = 0;                 /* Reset try counter */
  5659.             _packnum = (_packnum+1)%64;   /* and bump packet count */
  5660.             block_count++;
  5661.             return('C');                /* Switch state to Complete */
  5662.  
  5663.         case 'E':                       /* Error packet received */
  5664.             return('A');                /* abort */
  5665.  
  5666.         case FALSE: return(_state);      /* Receive failure, stay in B */
  5667.  
  5668.         default:    return ('A');       /* Other, "abort" */
  5669.    }
  5670. }
  5671.  
  5672.  
  5673. /*
  5674.  *  r e c s w
  5675.  *
  5676.  *  This is the _state table switcher for receiving files.
  5677.  */
  5678.  
  5679. void    recsw(void)
  5680.         {
  5681.         switch(_state)
  5682.             {
  5683.             case 'R':   _state = rinit(); return;   /* Receive-Init */
  5684.             case 'F':   _state = rfile(); return;   /* Receive-File */
  5685.             case 'D':   _state = rdata(); return;   /* Receive-Data */
  5686.             case 'C':   transferring_file=FALSE;    /* Complete state */
  5687.                         beep();
  5688.                         return;
  5689.             case 'A':   transferring_file=FALSE;    /* "Abort"  state */
  5690.                         beep();
  5691.                         xfr_abort = TRUE;
  5692.                         return;
  5693.             default:    transferring_file=FALSE;            /* Unknown, fail */
  5694.                         beep();
  5695.                         xfr_abort = TRUE;
  5696.                         return;
  5697.             }
  5698.         }
  5699.  
  5700.  
  5701.  
  5702. /*
  5703.  *  r i n i t
  5704.  *
  5705.  *  Receive Initialization
  5706.  */
  5707.  
  5708. char rinit()
  5709. {
  5710. static    int num;                            /* Packet number */
  5711. static    int len;                            /* length */
  5712.  
  5713.     if (!rpack_done) goto rpack_continue;
  5714.  
  5715.     num = len = 0;
  5716.     if (error_count++ > MAXTRY) return('A'); /* If too many tries, "abort" */
  5717.  
  5718. rpack_continue:
  5719.     switch(rpack(&len,&num,_packet))     /* Get a packet */
  5720.     {
  5721.         case 'I':  return(_state);       /* Incomplete */
  5722.  
  5723.         case 'S':                       /* Send-Init */
  5724.             rpar(_packet);               /* Get the other side's init data */
  5725.             spar(_packet);               /* Fill up packet with my init info */
  5726.             spack((char)'Y',_packnum,10,_packet);/* ACK with my parameters */
  5727.             _oldtry = error_count;            /* Save old try count */
  5728.             error_count = 0;                 /* Start a new counter */
  5729.             _packnum = (_packnum+1)%64;   /* Bump packet number, mod 64 */
  5730.             block_count++;
  5731.             return('F');                /* Enter File-Receive state */
  5732.  
  5733.         case 'E':                       /* Error packet received */
  5734.             return('A');                /* abort */
  5735.  
  5736.         case FALSE:                     /* Didn't get packet */
  5737.             spack((char)'N',_packnum,0,NULL);  /* Return a NAK */
  5738.             return(_state);              /* Keep trying */
  5739.  
  5740.         default:     return('A');       /* Some other packet type, "abort" */
  5741.     }
  5742. }
  5743.  
  5744.  
  5745. /*
  5746.  *  r f i l e
  5747.  *
  5748.  *  Receive File Header
  5749.  */
  5750.  
  5751. char rfile()
  5752. {
  5753. static    int num;                            /* Packet number */
  5754. static    int len;                            /* length */
  5755. static    int fch_cnt;                        /* filename char count */
  5756.  
  5757.     if (!rpack_done) goto rpack_continue;
  5758.  
  5759.     num = len = fch_cnt = 0;
  5760.     if (error_count++ > MAXTRY) return('A'); /* "abort" if too many tries */
  5761.  
  5762. rpack_continue:
  5763.     switch(rpack(&len,&num,_packet))     /* Get a packet */
  5764.     {
  5765.         case 'I':  return(_state);       /* Incomplete */
  5766.  
  5767.         case 'S':                       /* Send-Init, maybe our ACK lost */
  5768.             if (_oldtry++ > MAXTRY) return('A'); /* If too many tries "abort" */
  5769.             if (num == ((_packnum==0) ? 63:_packnum-1)) /* Previous packet, mod 64? */
  5770.             {                           /* Yes, ACK it again with  */
  5771.                 spar(_packet);           /* our Send-Init parameters */
  5772.                 spack((char)'Y',num,10,_packet);
  5773.                 error_count = 0;             /* Reset try counter */
  5774.                 return(_state);          /* Stay in this state */
  5775.             }
  5776.             else return('A');           /* Not previous packet, "abort" */
  5777.  
  5778.         case 'Z':                       /* End-Of-File */
  5779.             if (_oldtry++ > MAXTRY) return('A');
  5780.             if (num == ((_packnum==0) ? 63:_packnum-1)) /* Previous packet, mod 64? */
  5781.             {                           /* Yes, ACK it again. */
  5782.                 spack((char)'Y',num,0,NULL);
  5783.                 error_count = 0;
  5784.                 return(_state);          /* Stay in this state */
  5785.             }
  5786.             else return('A');           /* Not previous packet, "abort" */
  5787.  
  5788.         case 'F':                       /* File Header (just what we want) */
  5789.             if (num != _packnum) return('A');  /* The packet number must be right */
  5790.             _packet[12] = '\0';
  5791.             setmem(filename, 80, 0);
  5792.             while (_packet[fch_cnt] && fch_cnt < 8 && _packet[fch_cnt] != '.')
  5793.                 {
  5794.                 filename[fch_cnt] = _packet[fch_cnt];
  5795.                 fch_cnt++;
  5796.                 }
  5797.             if (_packet[fch_cnt] == '.')
  5798.                 while (_packet[fch_cnt] && fch_cnt < 12)
  5799.                     {
  5800.                     filename[fch_cnt] = _packet[fch_cnt];
  5801.                     fch_cnt++;
  5802.                     }
  5803.             strcpy(string2, filename);
  5804.             strcpy(filename, kermit_path);
  5805.             strcat(filename, string2);
  5806.             if ((transfer_handle=DosCreate(filename))==-1) /* open new file */
  5807.                 {
  5808.                 spack((char)'E',_packnum,17,"file create error");  /* Send error packet */
  5809.                 return('A');
  5810.                 }
  5811.  
  5812.             spack((char)'Y',_packnum,0,NULL);  /* Acknowledge the file header */
  5813.             _oldtry = error_count;            /* Reset try counters */
  5814.             error_count = 0;                 /* ... */
  5815.             _packnum = (_packnum+1)%64;   /* Bump packet number, mod 64 */
  5816.             block_count++;
  5817.             return('D');                /* Switch to Data state */
  5818.  
  5819.         case 'B':                       /* Break transmission (EOT) */
  5820.             if (num != _packnum) return ('A'); /* Need right packet number here */
  5821.             spack((char)'Y',_packnum,0,NULL);  /* Say OK */
  5822.             return('C');                /* Go to complete state */
  5823.  
  5824.         case 'E':                       /* Error packet received */
  5825.             return('A');                /* abort */
  5826.  
  5827.         case FALSE:                     /* Didn't get packet */
  5828.             spack((char)'N',_packnum,0,NULL);  /* Return a NAK */
  5829.             return(_state);              /* Keep trying */
  5830.  
  5831.         default:    return ('A');       /* Some other packet, "abort" */
  5832.     }
  5833. }
  5834.  
  5835. /*
  5836.  *  r d a t a
  5837.  *
  5838.  *  Receive Data
  5839.  */
  5840.  
  5841. char rdata()
  5842. {
  5843. static    int num;                            /* Packet number */
  5844. static    int len;                            /* length */
  5845.  
  5846.     if (!rpack_done) goto rpack_continue;
  5847.  
  5848.     num = len = 0;
  5849.     if (error_count++ > MAXTRY) return('A'); /* "abort" if too many tries */
  5850.  
  5851. rpack_continue:
  5852.     switch(rpack(&len,&num,_packet))     /* Get packet */
  5853.     {
  5854.         case 'I':  return(_state);       /* Incomplete */
  5855.  
  5856.         case 'D':                       /* Got Data packet */
  5857.             if (num != _packnum)         /* Right packet? */
  5858.             {                           /* No */
  5859.                 if (_oldtry++ > MAXTRY)
  5860.                     return('A');        /* If too many tries, abort */
  5861.                 if (num == ((_packnum==0) ? 63:_packnum-1)) /* Else check packet number */
  5862.                 {                       /* Previous packet again? */
  5863.                     spack((char)'Y',num,0,_packet); /* Yes, re-ACK it */
  5864.                     error_count = 0;         /* Reset try counter */
  5865.                     return(_state);      /* Don't write out data! */
  5866.                 }
  5867.                 else return('A');       /* sorry, wrong number */
  5868.             }
  5869.             /* Got data with right packet number */
  5870.             bufemp(_packet,len);         /* Write the data to the file */
  5871.             if (io_len == -1) return('A');
  5872.             spack((char)'Y',_packnum,0,NULL);  /* Acknowledge the packet */
  5873.             _oldtry = error_count;            /* Reset the try counters */
  5874.             error_count = 0;                 /* ... */
  5875.             _packnum = (_packnum+1)%64;   /* Bump packet number, mod 64 */
  5876.             block_count++;
  5877.             return('D');                /* Remain in data state */
  5878.  
  5879.         case 'F':                       /* Got a File Header */
  5880.             if (_oldtry++ > MAXTRY)
  5881.                 return('A');            /* If too many tries, "abort" */
  5882.             if (num == ((_packnum==0) ? 63:_packnum-1)) /* Else check packet number */
  5883.             {                           /* It was the previous one */
  5884.                 spack((char)'Y',num,0,NULL);  /* ACK it again */
  5885.                 error_count = 0;             /* Reset try counter */
  5886.                 return(_state);          /* Stay in Data state */
  5887.             }
  5888.             else return('A');           /* Not previous packet, "abort" */
  5889.  
  5890.         case 'Z':                       /* End-Of-File */
  5891.             if (num != _packnum) return('A');  /* Must have right packet number */
  5892.             spack((char)'Y',_packnum,0,NULL);  /* OK, ACK it. */
  5893.             DosClose(transfer_handle);           /* Close the file */
  5894.             _packnum = (_packnum+1)%64;   /* Bump packet number */
  5895.             block_count++;
  5896.             return('F');                /* Go back to Receive File state */
  5897.  
  5898.         case 'E':                       /* Error packet received */
  5899.             return('A');                /* abort */
  5900.  
  5901.         case FALSE:                     /* Didn't get packet */
  5902.             spack((char)'N',_packnum,0,NULL);  /* Return a NAK */
  5903.             return(_state);              /* Keep trying */
  5904.  
  5905.         default:     return('A');       /* Some other packet, "abort" */
  5906.     }
  5907. }
  5908.  
  5909. /*
  5910.  *  s p a c k
  5911.  *
  5912.  *  Send a Packet
  5913.  */
  5914.  
  5915. spack(type,num,len,data)
  5916. char type, *data;
  5917. int num, len;
  5918. {
  5919.     int i, j;                           /* Character loop counters */
  5920.     char chksum, buffer[100];           /* Checksum, packet buffer */
  5921.     register char *bufp;                /* Buffer pointer */
  5922.  
  5923.  
  5924.     bufp = buffer;                      /* Set up buffer pointer */
  5925.     for (i=1; i<=_pad; i++) 
  5926.         write_tty(&_padchar, 1);          /* Issue any padding */
  5927.  
  5928.     *bufp++ = SOH;                      /* Packet marker, ASCII 1 (SOH) */
  5929.     *bufp++ = tochar(len+3);            /* Send the character count */
  5930.     chksum  = tochar(len+3);            /* Initialize the checksum */
  5931.     *bufp++ = tochar(num);              /* Packet number */
  5932.     chksum += tochar(num);              /* Update checksum */
  5933.     *bufp++ = type;                     /* Packet type */
  5934.     chksum += type;                     /* Update checksum */
  5935.  
  5936.     for (i=0; i<len; i++)               /* Loop for all data characters */
  5937.     {
  5938.         *bufp++ = data[i];              /* Get a character */
  5939.         chksum += data[i];              /* Update checksum */
  5940.     }
  5941.     chksum = (((chksum&0300) >> 6)+chksum)&077; /* Compute final checksum */
  5942.     *bufp++ = tochar(chksum);           /* Put it in the packet */
  5943.     *bufp = _eol;                        /* Extra-packet line terminator */
  5944.     j = bufp - buffer + 1;
  5945.     write_tty(buffer, j);               /* Send the packet */
  5946.     return(0);
  5947. }
  5948.  
  5949. /*
  5950.  *  r p a c k
  5951.  *
  5952.  *  Read a Packet
  5953.  */
  5954.  
  5955. char rpack(len,num,data)
  5956. int  *len; 
  5957. int  *num;                              /* Packet length, number */
  5958. char *data;                             /* Packet data */
  5959. {
  5960. static    int  i;                             /* Data character number */
  5961. static    char t;                             /* Current input character */
  5962. static    int  ti;                            /* Current input character */
  5963. static    char type;                          /* Packet type */
  5964. static    char cchksum;                       /* Our (computed) checksum */
  5965. static    char rchksum;                       /* Checksum received from other host */
  5966. static    int  rp_state;
  5967.  
  5968.     if (rp_state == 0)
  5969.         {
  5970.         i = t = type = cchksum = rchksum = 0;
  5971.         timeout_ticks = tick_counter + 18l + (long) (_timint * 18);
  5972.         rp_state = 1;
  5973.         }
  5974.  
  5975. read_tty:
  5976.     if (!output_queue_empty)
  5977.         {
  5978.         timeout_ticks = tick_counter + 18l + (long) (_timint * 18);
  5979.         next_fg_slice = tick_counter;
  5980.         rpack_done = FALSE;
  5981.         return('I');
  5982.         }
  5983.  
  5984.     ti = get_modem();
  5985.     if (ti == -1)
  5986.         {
  5987.         if (tick_counter > timeout_ticks)
  5988.             {
  5989.             rpack_done = TRUE;
  5990.             rp_state   = 0;
  5991.             return(FALSE);
  5992.             }
  5993.         rpack_done = FALSE;
  5994.         return('I');
  5995.         }
  5996.  
  5997.     t = (unsigned char) ti;
  5998.     switch (rp_state)
  5999.         {
  6000.         case 1 : goto rp_soh;
  6001.         case 2 : goto rp_len;
  6002.         case 3 : goto rp_num;
  6003.         case 4 : goto rp_type;
  6004.         case 5 : goto rp_dat;
  6005.         case 6 : goto rp_chksum;
  6006.         case 7 : goto rp_eol;
  6007.         default: goto read_tty;
  6008.         }
  6009.  
  6010. rp_soh:
  6011.     t &= 0177;                     /* Handle parity */
  6012.     if (t == SOH) rp_state = 2;
  6013.     goto read_tty;
  6014.  
  6015. rp_len:
  6016.     if (!_image) t &= 0177;         /* Handle parity */
  6017.     if (t == SOH) goto rp_soh;      /* Resynchronize if SOH */
  6018.     cchksum = t;                    /* Start the checksum */
  6019.     *len = unchar(t) - 3;           /* Character count */
  6020.     rp_state = 3;
  6021.     goto read_tty;
  6022.  
  6023. rp_num:
  6024.     if (!_image) t &= 0177;          /* Handle parity */
  6025.     if (t == SOH) goto rp_soh;      /* Resynchronize if SOH */
  6026.     cchksum = cchksum + t;          /* Update checksum */
  6027.     *num = unchar(t);               /* Packet number */
  6028.     rp_state = 4;
  6029.     goto read_tty;
  6030.  
  6031. rp_type:
  6032.     if (!_image) t &= 0177;          /* Handle parity */
  6033.     if (t == SOH) goto rp_soh;      /* Resynchronize if SOH */
  6034.     cchksum = cchksum + t;          /* Update checksum */
  6035.     type = t;                       /* Packet type */
  6036.     if (*len == 0)
  6037.         rp_state = 6;
  6038.     else
  6039.         rp_state = 5;
  6040.     goto read_tty;
  6041.  
  6042. rp_dat:
  6043.     if (!_image) t &= 0177;      /* Handle parity */
  6044.     if (t == SOH) goto rp_soh;  /* Resynch if SOH */
  6045.     cchksum = cchksum + t;      /* Update checksum */
  6046.     data[i] = t;                /* Put it in the data buffer */
  6047.     if (++i == *len)
  6048.         rp_state = 6;
  6049.     goto read_tty;
  6050.  
  6051. rp_chksum:
  6052.     data[*len] = 0;                 /* Mark the end of the data */
  6053.     rchksum = unchar(t);            /* Convert to numeric */
  6054.     rp_state = 7;
  6055.     goto read_tty;
  6056.  
  6057. rp_eol:
  6058.     if (!_image) t &= 0177;         /* Handle parity */
  6059.     if (t == SOH) goto rp_soh;      /* Resynchronize if SOH */
  6060.     rpack_done = TRUE;              /* Got checksum, done */
  6061.     rp_state = 0;
  6062.  
  6063.     /* Fold in bits 7,8 to compute */
  6064.     /* final checksum */
  6065.  
  6066.     cchksum = (((cchksum&0300) >> 6)+cchksum)&077;
  6067.     if (cchksum != rchksum) return(FALSE);
  6068.  
  6069.     return(type);                       /* All OK, return packet type */
  6070. }
  6071.  
  6072.  
  6073. /*
  6074.  *  b u f i l l
  6075.  *
  6076.  *  Get a bufferful of data from the file that's being sent.
  6077.  *  Only control-quoting is done; 8-bit & repeat count prefixes are
  6078.  *  not handled.
  6079.  */
  6080.  
  6081. bufill(buffer)
  6082. char buffer[];                          /* Buffer */
  6083. {
  6084.     int  i  = 0;                        /* Loop index */
  6085.     char t  = 0;                        /* Char read from file */
  6086.     char t7 = 0;                        /* 7-bit version of above */
  6087.  
  6088.     i = 0;                              /* Init data buffer pointer */
  6089.  
  6090.     while ((io_len = DosRead(transfer_handle, &t, 1)) != 0)
  6091.     {
  6092.         if (io_len == -1) return -1;
  6093.  
  6094.         t7 = t & 0177;                  /* Get low order 7 bits */
  6095.  
  6096.         if (t7 < SP || t7==DEL || t7==_quote) /* Does this char require */
  6097.         {                                   /* special handling? */
  6098.             if (t=='\n' && !_image)
  6099.             {                           /* Do LF->CRLF mapping if !_image */
  6100.                 buffer[i++] = _quote;
  6101.                 buffer[i++] = ctl('\r');
  6102.             }
  6103.             buffer[i++] = _quote;        /* Quote the character */
  6104.             if (t7 != _quote)
  6105.             {
  6106.                 t = ctl(t);             /* and uncontrolify */
  6107.                 t7 = ctl(t7);
  6108.             }
  6109.         }
  6110.         if (_image)
  6111.             buffer[i++] = t;            /* Deposit the character itself */
  6112.         else
  6113.             buffer[i++] = t7;
  6114.  
  6115.         if (i >= _spsiz-8) return(i);    /* Check length */
  6116.     }
  6117.     if (i==0) return(-1);              /* Wind up here only on EOF */
  6118.     return(i);                          /* Handle partial buffer */
  6119. }
  6120.  
  6121.  
  6122. /*
  6123.  *      b u f e m p
  6124.  *
  6125.  *  Put data from an incoming packet into a file.
  6126.  */
  6127.  
  6128. bufemp(buffer,len)
  6129. char  buffer[];                         /* Buffer */
  6130. int   len;                              /* Length */
  6131. {
  6132.     int i;                              /* Counter */
  6133.     char t;                             /* Character holder */
  6134.  
  6135.     for (i=0; i<len; i++)               /* Loop thru the data field */
  6136.     {
  6137.         t = buffer[i];                  /* Get character */
  6138.         if (t == MYQUOTE)               /* Control _quote? */
  6139.         {                               /* Yes */
  6140.             t = buffer[++i];            /* Get the _quoted character */
  6141.             if ((t & 0177) != MYQUOTE)  /* Low order bits match _quote char? */
  6142.                 t = ctl(t);             /* No, uncontrollify it */
  6143.         }
  6144.         if (t==CR && !_image)            /* Don't pass CR if in _image mode */
  6145.             continue;
  6146.  
  6147.         io_len = DosWrite(transfer_handle, &t, 1);
  6148.         if (io_len == -1)
  6149.             return -1;
  6150.     }
  6151.  
  6152.     return(0);
  6153. }
  6154.  
  6155.  
  6156. /*
  6157.  *  g n x t f l
  6158.  *
  6159.  *  Get next file in a file group
  6160.  */
  6161.  
  6162. gnxtfl()
  6163. {
  6164.     if (_filecount == 0)
  6165.         return(FALSE);                  /* If no more, fail */
  6166.  
  6167.     strcpy(filename, *_filelist);
  6168.     _filelist++;
  6169.     _filecount--;
  6170.     return(TRUE);                       /* else succeed */
  6171. }
  6172.  
  6173.  
  6174. /*
  6175.  *  s p a r
  6176.  *
  6177.  *  Fill the data array with my send-init parameters
  6178.  *
  6179.  */
  6180.  
  6181. spar(data)
  6182. char data[];
  6183. {
  6184.     data[0] = tochar(MAXPACKSIZ);       /* Biggest packet I can receive */
  6185.     data[1] = tochar(MYTIME);           /* When I want to be timed out */
  6186.     data[2] = tochar(MYPAD);            /* How much padding I need */
  6187.     data[3] = ctl(MYPCHAR);             /* Padding character I want */
  6188.     data[4] = tochar(MYEOL);            /* End-Of-Line character I want */
  6189.     data[5] = MYQUOTE;                  /* Control-Quote character I send */
  6190.     data[6] = (char) 'N';               /* Say no to 8th-bit quoting */
  6191.     data[7] = (char) '1';               /* Single-char Checksum */
  6192.     data[8] = (char) ' ';               /* Repeat char (none) */
  6193.     data[9] = (char) ' ';               /* No particular capabilities */
  6194.     return(0);
  6195. }
  6196.  
  6197. /*  r p a r
  6198.  *
  6199.  *  Get the other host's send-init parameters
  6200.  *
  6201.  */
  6202.  
  6203. rpar(data)
  6204. char data[];
  6205. {
  6206.     _spsiz = unchar(data[0]);            /* Maximum send packet size */
  6207.     _timint = unchar(data[1]);           /* When I should time out */
  6208.     _pad = unchar(data[2]);              /* Number of pads to send */
  6209.     _padchar = ctl(data[3]);             /* Padding character to send */
  6210.     _eol = unchar(data[4]);              /* EOL character I must send */
  6211.     _quote = data[5];                    /* Incoming data _quote character */
  6212.  
  6213.     if (_timint < MINTIM) _timint = MINTIM;
  6214.     if (_timint > MAXTIM) _timint = MAXTIM;
  6215.     return(0);
  6216. }
  6217.  
  6218.  
  6219. void    background_kermit_send(void)
  6220.         {
  6221.         if (transfer_init)
  6222.             {
  6223.             transfer_init = FALSE;
  6224.             _state   = 'S';         /* Send initiate is the start state */
  6225.             _packnum = 0;           /* Initialize message number */
  6226.             _timint  = MYTIME;
  6227.             if (gnxtfl() == FALSE)
  6228.                 {
  6229.                 transferring_file = FALSE;
  6230.                 return;
  6231.                 }
  6232.             }
  6233.  
  6234.         if (user_abort)
  6235.             {
  6236.             xfr_abort = TRUE;
  6237.             user_abort = FALSE;
  6238.             beep();
  6239.             delay(100);
  6240.             beep();
  6241.             transferring_file = FALSE;
  6242.             return;
  6243.             }
  6244.  
  6245.         if (!output_queue_empty)
  6246.             {
  6247.             next_fg_slice = tick_counter;
  6248.             return;
  6249.             }
  6250.  
  6251.         sendsw();
  6252.         }
  6253.  
  6254.  
  6255. void    background_kermit_recv(void)
  6256.         {
  6257.         if (transfer_init)
  6258.             {
  6259.             transfer_init = FALSE;
  6260.             _state   = 'R';         /* Receive-Init is the start state */
  6261.             _packnum = 0;           /* Initialize message number */
  6262.             _timint  = MYTIME;
  6263.             }
  6264.  
  6265.         if (user_abort)
  6266.             {
  6267.             xfr_abort = TRUE;
  6268.             user_abort = FALSE;
  6269.             beep();
  6270.             delay(100);
  6271.             beep();
  6272.             unlink(filename);
  6273.             transferring_file = FALSE;
  6274.             return;
  6275.             }
  6276.  
  6277.         recsw();
  6278.         }
  6279.  
  6280.  
  6281. void    background_ascii_send(void)
  6282.         {
  6283.         int  r, i;
  6284.         char c;
  6285.  
  6286.         if (transfer_init)
  6287.             {
  6288.             transfer_init = FALSE;
  6289.             oldx = oldy = 1;
  6290.             transfer_handle = DosOpen(filename, 0);
  6291.             if (transfer_handle == -1)
  6292.                 {
  6293.                 transferring_file = FALSE;
  6294.                 xfr_abort = TRUE;
  6295.                 return;
  6296.                 }
  6297.             }
  6298.  
  6299.         if (user_abort)
  6300.             {
  6301.             DosClose(transfer_handle);
  6302.             xfr_abort = TRUE;
  6303.             user_abort = FALSE;
  6304.             beep();
  6305.             transferring_file = FALSE;
  6306.             return;
  6307.             }
  6308.  
  6309.         if (in_popup)
  6310.             {
  6311.             window(2, 17, 79, 24);
  6312.             gotoxy(oldx, oldy);
  6313.             textcolor(msg_fg);
  6314.             textbackground(msg_bg);
  6315.             while (tick_counter < next_fg_slice - 1l
  6316.                 && (i = get_modem()) != -1 )
  6317.                     display_char( (char) i);
  6318.             }
  6319.  
  6320.         if (!output_queue_empty)
  6321.             {
  6322.             next_fg_slice = tick_counter;
  6323.             goto bg_ascii_exit;
  6324.             }
  6325.  
  6326.         io_len = DosRead(transfer_handle, xmodem_area, 512);
  6327.         if (io_len <= 0)
  6328.             {
  6329.             transferring_file = FALSE;
  6330.             DosClose(transfer_handle);
  6331.             beep();
  6332.             goto bg_ascii_exit;
  6333.             }
  6334.  
  6335.         for (r=0; r<io_len; r++)
  6336.             {
  6337.             c = xmodem_area[r];
  6338.             if ( (c != LINEFEED) || (c == LINEFEED && send_crlf) )
  6339.                 send_char(c);
  6340.             delay(char_delay);
  6341.             if (c == CR)
  6342.                 delay(line_delay);
  6343.             }
  6344.  
  6345.         if (in_popup)
  6346.             while (tick_counter < next_fg_slice
  6347.                 && (i = get_modem()) != -1 )
  6348.                     display_char( (char) i);
  6349.  
  6350.         byte_count += (long) io_len;
  6351.  
  6352. bg_ascii_exit:
  6353.         if (in_popup)
  6354.             {
  6355.             oldx = wherex();
  6356.             oldy = wherey();
  6357.             window(1, 1, 80, 25);
  6358.             }
  6359.         }
  6360.  
  6361.  
  6362. void    background_ascii_recv(void)
  6363.         {
  6364.         char c;
  6365.  
  6366.         if (transfer_init)
  6367.             {
  6368.             transfer_init = FALSE;
  6369.             oldx = oldy = 1;
  6370.             transfer_handle  = DosCreate(filename);
  6371.             if (transfer_handle == -1)
  6372.                 {
  6373.                 transferring_file = FALSE;
  6374.                 xfr_abort = TRUE;
  6375.                 return;
  6376.                 }
  6377.             }
  6378.  
  6379.         if (user_abort)
  6380.             {
  6381.             xfr_abort = TRUE;
  6382.             user_abort = FALSE;
  6383.             DosClose(transfer_handle);
  6384.             beep();
  6385.             transferring_file = FALSE;
  6386.             return;
  6387.             }
  6388.  
  6389.  
  6390.         if (in_popup)
  6391.             {
  6392.             window(2, 17, 79, 24);
  6393.             gotoxy(oldx, oldy);
  6394.             textcolor(msg_fg);
  6395.             textbackground(msg_bg);
  6396.             }
  6397.  
  6398.         if ((xc = get_modem()) != -1)
  6399.             {
  6400.             c = (char) xc;
  6401.             if (in_popup) display_char(c);
  6402.             io_len = DosWrite(transfer_handle, &c, 1);
  6403.             if (io_len == -1)
  6404.                 {
  6405.                 xfr_abort = TRUE;
  6406.                 user_abort = FALSE;
  6407.                 DosClose(transfer_handle);
  6408.                 beep();
  6409.                 transferring_file = FALSE;
  6410.                 return;
  6411.                 }
  6412.             timeout_ticks = tick_counter + timeout_value;
  6413.             byte_count++;
  6414.             }
  6415.         else
  6416.         if (tick_counter > timeout_ticks)
  6417.             {
  6418.             timeout_ticks = tick_counter + timeout_value;
  6419.             beep();
  6420.             delay(100);
  6421.             beep();
  6422.             }
  6423.  
  6424.         if (in_popup)
  6425.             {
  6426.             oldx = wherex();
  6427.             oldy = wherey();
  6428.             window(1, 1, 80, 25);
  6429.             }
  6430.         }
  6431.  
  6432. /* ----------------------------------------------- */
  6433.  
  6434. void    do_transfer(void)
  6435.         {
  6436.         if (tick_counter < next_bg_slice)
  6437.             return;
  6438.  
  6439.         if (in_popup)
  6440.             goto calc_slice;
  6441.  
  6442.         disable();
  6443.         old_ss = _SS;
  6444.         old_sp = _SP;
  6445.         _SS = our_ss;
  6446.         _SP = our_sp;
  6447.         enable();
  6448.  
  6449.         break_state = getcbrk();
  6450.         oldint1b = getvect(0x1b);
  6451.         setvect(0x1b, int1b);
  6452.         oldint1c = getvect(0x1c);
  6453.         setvect(0x1c, int1c);
  6454.         oldint23 = getvect(0x23);
  6455.         setvect(0x23, int23);
  6456.         oldint24 = getvect(0x24);
  6457.         setvect(0x24, int24);
  6458.         olddta_ptr = getdta();
  6459.         setdta(ourdta_ptr);
  6460.         _AX = 0x5100;
  6461.         geninterrupt(0x21);
  6462.         oldpsp = _BX;
  6463.         _AX = 0x5000;
  6464.         _BX = ourpsp;
  6465.         geninterrupt(0x21);
  6466.  
  6467. calc_slice:
  6468.         if (in_popup)
  6469.             next_fg_slice = tick_counter + 9l;
  6470.         else
  6471.             next_fg_slice = tick_counter + background_ticks;
  6472.  
  6473.         while (transferring_file && tick_counter < next_fg_slice)
  6474.             {
  6475.             switch (transfer_type)
  6476.                 {
  6477.                 case XMODEM_RECV : {background_xy_recv(); break;}
  6478.                 case YMODEM_RECV : {background_xy_recv(); break;}
  6479.                 case XMODEM_SEND : {background_xy_send(); break;}
  6480.                 case YMODEM_SEND : {background_xy_send(); break;}
  6481.                 case KERMIT_SEND : {background_kermit_send(); break;}
  6482.                 case KERMIT_RECV : {background_kermit_recv(); break;}
  6483.                 case ASCII_SEND  : {background_ascii_send(); break;}
  6484.                 case ASCII_RECV  : {background_ascii_recv(); break;}
  6485.                 default          : {
  6486.                                    if (capturing && !in_popup) 
  6487.                                         get_modem();
  6488.                                    break;
  6489.                                    }
  6490.                 }
  6491.             }
  6492.  
  6493.         if (in_popup)
  6494.             {
  6495.             next_bg_slice = tick_counter + 1l;
  6496.             return;
  6497.             }
  6498.  
  6499.         if (transferring_file && tick_counter > commit_ticks)
  6500.             {
  6501.             if (capturing)
  6502.                 DosClose(dup(capture_handle));
  6503.             if (transfer_type != NO_TRANSFER)
  6504.                 DosClose(dup(transfer_handle));
  6505.             commit_ticks = tick_counter + 182l;
  6506.             }
  6507.  
  6508.         next_bg_slice = tick_counter + foreground_ticks;
  6509.  
  6510.         _AX = 0x5000;
  6511.         _BX = oldpsp;
  6512.         geninterrupt(0x21);
  6513.         setdta(olddta_ptr);
  6514.         setvect(0x24, oldint24);
  6515.         setvect(0x23, oldint23);
  6516.         setvect(0x1c, oldint1c);
  6517.         setvect(0x1b, oldint1b);
  6518.         setcbrk(break_state);
  6519.  
  6520. reset_bg_stack:
  6521.         disable();
  6522.         _SS = old_ss;
  6523.         _SP = old_sp;
  6524.         enable();
  6525.         }
  6526.  
  6527.  
  6528.  
  6529. void    do_popup(void)
  6530.         {
  6531.         disable();
  6532.         old_ss = _SS;
  6533.         old_sp = _SP;
  6534.         _SS = our_ss;
  6535.         _SP = our_sp;
  6536.         enable();
  6537.  
  6538.         if (de_install)
  6539.             {
  6540.             if (!okay_to_unload()) goto do_popup_exit;
  6541.             _AX = 0x5000;
  6542.             _BX = ourpsp;
  6543.             geninterrupt(0x21);
  6544.             close_port();
  6545.             setvect(0x08, oldint08);
  6546.             setvect(0x28, oldint28);
  6547.             setvect(0x09, oldint09);
  6548.             setvect(0x10, oldint10);
  6549.             setvect(0x13, oldint13);
  6550.             setvect(0x16, oldint16);
  6551.             setvect(0x21, oldint21);
  6552.             _ES = ourpsp;
  6553.             _BX = 0x2c;
  6554.             asm   mov es, es:[bx]
  6555.             _AH = 0x49;
  6556.             geninterrupt(0x21);
  6557.             _ES = ourpsp;
  6558.             _AH = 0x49;
  6559.             geninterrupt(0x21);
  6560.             asm   mov ax, word ptr next_mcb+2
  6561.             asm   inc ax
  6562.             asm   mov es, ax
  6563.             _AH = 0x49;
  6564.             geninterrupt(0x21);
  6565.             _AX = 0x4c00;
  6566.             geninterrupt(0x21);
  6567.             }
  6568.  
  6569. process_popup:
  6570.         curr_vid_mode = get_vid_mode();
  6571.         if (curr_vid_mode != 2
  6572.             && curr_vid_mode != 3
  6573.             && curr_vid_mode != 7)
  6574.                 {
  6575.                 beep();
  6576.                 delay(100);
  6577.                 beep();
  6578.                 hot_flag = FALSE;
  6579.                 goto do_popup_exit;
  6580.                 }
  6581.  
  6582.         if (in_background) goto regain_com_port;
  6583.  
  6584.         break_state = getcbrk();
  6585.         oldint1b = getvect(0x1b);
  6586.         setvect(0x1b, int1b);
  6587.         oldint1c = getvect(0x1c);
  6588.         setvect(0x1c, int1c);
  6589.         oldint23 = getvect(0x23);
  6590.         setvect(0x23, int23);
  6591.         oldint24 = getvect(0x24);
  6592.         setvect(0x24, int24);
  6593.         olddta_ptr = getdta();
  6594.         setdta(ourdta_ptr);
  6595.         _AX = 0x5100;
  6596.         geninterrupt(0x21);
  6597.         oldpsp = _BX;
  6598.         _AX = 0x5000;
  6599.         _BX = ourpsp;
  6600.         geninterrupt(0x21);
  6601.  
  6602. regain_com_port:
  6603.         switch (port_id)
  6604.             {
  6605.             case 1 : vecthold = getvect(0x0c); break;
  6606.             case 2 : vecthold = getvect(0x0b); break;
  6607.             case 3 : vecthold = getvect(0x0c); break;
  6608.             case 4 : vecthold = getvect(0x0b); break;
  6609.             default: vecthold = NULL;
  6610.             }
  6611.         if (vectsave != vecthold)
  6612.             open_port(port_id,speedsave,paritysave,bitssave,stop_bitsave);
  6613.  
  6614.         save_screen(1,1,80,25, app_screen, 
  6615.                            &app_cursor_save, &app_cursor_type);
  6616.         actual_popup();
  6617.         restore_screen(1,1,80,25, app_screen, 
  6618.                            &app_cursor_save, &app_cursor_type);
  6619.  
  6620.         if (in_background) goto do_popup_exit;
  6621.  
  6622.         _AX = 0x5000;
  6623.         _BX = oldpsp;
  6624.         geninterrupt(0x21);
  6625.         setdta(olddta_ptr);
  6626.         setvect(0x24, oldint24);
  6627.         setvect(0x23, oldint23);
  6628.         setvect(0x1c, oldint1c);
  6629.         setvect(0x1b, oldint1b);
  6630.         setcbrk(break_state);
  6631.  
  6632. do_popup_exit:
  6633.         disable();
  6634.         _SS = old_ss;
  6635.         _SP = old_sp;
  6636.         enable();
  6637.         }
  6638.  
  6639. /* ------------------------------------------- */
  6640.  
  6641. void    main(int argc, char *argv[])
  6642.         {
  6643.         getdate(&today);
  6644.  
  6645.         _AX = 'SN';
  6646.         geninterrupt(0x16);
  6647.         if (_AX == 'sn')
  6648.             {
  6649.             cprintf("\r\n");
  6650.             cprintf("The background comm. program was already loaded.\r\n");
  6651.             cprintf("Use ALT/RIGHT-SHIFT to activate it.\r\n");
  6652.             exit(1);
  6653.             }
  6654.  
  6655.         if (_osmajor < 2)
  6656.             {
  6657.             cprintf("\r\n");
  6658.             cprintf("Early versions of DOS not supported...\r\n");
  6659.             exit(1);
  6660.             }
  6661.  
  6662.         if ( (our_stack = malloc(MY_STK_SIZE)) == NULL)
  6663.             {
  6664.             cprintf("\r\n");
  6665.             cprintf("Insufficient memory...\r\n");
  6666.             exit(1);
  6667.             }
  6668.         our_ss    = _DS;
  6669.         our_sp    = (unsigned) our_stack + (MY_STK_SIZE - 2);
  6670.  
  6671.         flow_control = TRUE;
  6672.         rpack_done   = TRUE;
  6673.         setmem(holdstr, 81, 0);
  6674.         init_line_pointers();
  6675.         mouse_exists = TRUE;
  6676.  
  6677.         if ((get_config("comm.cfg")) != 0)
  6678.             {
  6679.             sprintf(string1, "Error with 'comm.cfg': %s.", 
  6680.                 config_msg[config_error]);
  6681.             cprintf("\r\n");
  6682.             cprintf("Program not loaded.  The configuration file is in error.\r\n");
  6683.             cprintf("%s\r\n", string1);
  6684.             cprintf(
  6685.                "Please use the text editor to correct the 'comm.cfg' file.\r\n");
  6686.             exit(1);
  6687.             }
  6688.  
  6689.         if (mouse_exists)
  6690.             mouse_init();
  6691.  
  6692.         if (mouse_exists && mouse_shared)
  6693.             show_mouse();
  6694.  
  6695.         _AX = 0x3400;
  6696.         geninterrupt(0x21);
  6697.         temp2 = _BX;
  6698.         temp1 = _ES;
  6699.  
  6700.         indos_ptr = MK_FP(temp1, temp2);
  6701.         if (_osmajor == 2)
  6702.             indos2_ptr = MK_FP(temp1, temp2 + 1);
  6703.         else
  6704.             indos2_ptr = MK_FP(temp1, temp2 - 1);
  6705.  
  6706.         delay(10);
  6707.         prtsc_flag_ptr = MK_FP(0x0050, 0x0000);
  6708.         kbd_flag_ptr   = MK_FP(0x0040, 0x0017);
  6709.         oldint0b = getvect(0x0b);
  6710.         oldint0c = getvect(0x0c);
  6711.  
  6712.         i = open_port(our_port,our_speed,our_par,our_bits,our_stop);
  6713.         if (i == -1)
  6714.             {
  6715.             cprintf("\r\n");
  6716.             cprintf(
  6717.               "Program not loaded  -- comm port %d could not be initialized.\r\n", our_port);
  6718.             cprintf(
  6719.               "Please use the text editor to correct the 'comm.cfg' file.\r\n");
  6720.             exit (1);
  6721.             }
  6722.  
  6723.         if (!carrier())
  6724.             if (strlen(modem_init) != 0)
  6725.                 {
  6726.                 flag_save = echo_flag;
  6727.                 echo_flag = FALSE;
  6728.                 cprintf("\r\nInitializing modem....");
  6729.                 send_string(modem_init);
  6730.                 echo_flag = flag_save;
  6731.                 }
  6732.  
  6733.         cprintf("\r\n\r\n");
  6734.         cprintf("Background Communications Program is loaded.\r\n");
  6735.         cprintf("Press ALT/RIGHT-SHIFT to activate the program.\r\n\r\n");
  6736.  
  6737.         ourdta_ptr = getdta();
  6738.         _AX = 0x5100;
  6739.         geninterrupt(0x21);
  6740.         ourpsp = _BX;
  6741.  
  6742.         our_mcb       = MK_FP(ourpsp-1, 0);
  6743.         our_mcb_size  = MK_FP(ourpsp-1, 3);
  6744.  
  6745.         oldint08 = getvect(0x08);
  6746.         oldint09 = getvect(0x09);
  6747.         oldint10 = getvect(0x10);
  6748.         oldint13 = getvect(0x13);
  6749.         oldint16 = getvect(0x16);
  6750.         oldint21 = getvect(0x21);
  6751.         oldint28 = getvect(0x28);
  6752.  
  6753.         asm     mov ax, word ptr oldint10
  6754.         asm     mov word ptr cs:[0004h], ax
  6755.         asm     mov ax, word ptr oldint10+2
  6756.         asm     mov word ptr cs:[0006h], ax
  6757.  
  6758.         asm     mov ax, word ptr oldint13
  6759.         asm     mov word ptr cs:[0008h], ax
  6760.         asm     mov ax, word ptr oldint13+2
  6761.         asm     mov word ptr cs:[000Ah], ax
  6762.  
  6763.         asm     mov ax, word ptr oldint21
  6764.         asm     mov word ptr cs:[0000h], ax
  6765.         asm     mov ax, word ptr oldint21+2
  6766.         asm     mov word ptr cs:[0002h], ax
  6767.  
  6768.         setvect(0x10, int10);
  6769.         setvect(0x13, int13);
  6770.         setvect(0x16, int16);
  6771.         setvect(0x21, int21);
  6772.         setvect(0x09, int09);
  6773.         setvect(0x28, int28);
  6774.         setvect(0x08, int08);
  6775.  
  6776.         hot_flag   = TRUE;
  6777.  
  6778.         paragraphs = (our_ss + (our_sp >> 4) + 1) - ourpsp;
  6779.         keep(0, paragraphs);
  6780.         }
  6781.  
  6782.  
  6783.